使用共享内存进行通信的代码和运行情况分析,共享内存的特点(拷贝次数,访问控制),加入命名管道进行通信的代码和运行情况分析

目录

示例代码

头文件(comm.hpp)

log.hpp

基础版 -- 服务端

代码

运行情况

加入客户端

代码

运行情况

两端进行通信 

客户端

代码

注意点

服务端

代码

两端运行情况

共享内存特点

拷贝次数少

管道的拷贝次数

共享内存的拷贝次数

没有访问控制

管道

共享内存

并发问题

添加访问控制(通过管道)

代码

头文件

服务端

客户端

运行情况


我们已经介绍了共享内存多个接口的使用,接下来就开始实际调用一下吧

示例代码

头文件(comm.hpp)

#ifndef COMM_H
#define COMM_H#include <iostream>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#include <string>
#include <fcntl.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "log.hpp"
#include <assert.h>using namespace std;#define PATH_NAME "/home/mufeng"
#define PROJ_ID 0x1234
#define SUM_SIZE 4096#endif

log.hpp

我们将不同的报错信息分成4种等级

#pragma once#include <iostream>
#include <string>
#include <time.h>using namespace std;#define debug 0
#define notice 1
#define warning 2
#define error 3const string msg[]{"debug", "notice", "warning", "error"};ostream &log(string message, int level)
{cout << "|" << (unsigned)time(nullptr) << "|" << message << "|" << msg[level] << "|";return cout;
}

基础版 -- 服务端

代码

注意我们使用assert来确保调用成功,并且成功后就进行日志打印

#include"comm.hpp"int main(){key_t key = ftok(PATH_NAME, PROJ_ID);assert(key != -1);(void)key;log("key created success", debug) << ", key : " << key << endl;int shmid = shmget(key, SUM_SIZE, IPC_CREAT|IPC_EXCL|0666);assert(shmid != -1);(void)shmid;log("shm created success", debug) << ", shmid : " << shmid << endl;sleep(3);char *addres = (char *)shmat(shmid, nullptr, 0);log("process link success", debug) << endl;sleep(3);int ret = shmdt(addres);assert(ret != -1);(void)ret;log("process unlink success", debug) << endl;sleep(3);ret = shmctl(shmid, IPC_RMID, nullptr);assert(ret != -1);(void)ret;log("shm unlink success", debug) << endl;sleep(3);return 0;
}

运行情况

监控共享内存的使用情况(while :;do ipcs -m ;sleep 1;done):

  • 连接数从0 -> 1
  • 解除连接后,连接数从1 -> 0
  • 删除后,共享内存块消失

 

加入客户端

代码

相似的操作

但我们的客户端不需要创建新的共享内存,而是使用服务端使用的那个:

int main()
{key_t key = ftok(PATH_NAME, PROJ_ID);if (key < 0){log("key created failed", error) << ", client key : " << key << endl;}int shmid = shmget(key, SUM_SIZE, 0);if (shmid < 0){log("shmid created failed", error) << ", client shmid : " << shmid << endl;}char *addres = (char *)shmat(shmid, nullptr, 0);if (addres == nullptr){log("process link failed", error) << endl;}sleep(3);int ret = shmdt(addres);if (ret < 0){log("process unlink failed", error) << endl;}sleep(3);//这里不需要删除,服务端会将这块内存释放掉return 0;
}

运行情况

连接数从0 -> 1 -> 2 -> 1 -> 0:

 

两端进行通信 

客户端

  • 客户端一般是发送内容给服务端
  • 这里我们将从标准输入(也就是键盘)读入的内容,写入到addres中
  • 如果读到了quit,就退出
代码
//通信while(true){ssize_t size=read(0,addres,SUM_SIZE-1);if(size>0){addres[size-1]=0;if(strcmp(addres,"quit")==0){break;}}}
注意点
  • 我们在输入时,实际上会将按的回车也读入
  • 但我们判断的是"quit",它不包括换行符
  • 所以需要将addres从读入的那个换行符开始,设置为0

服务端

  • 从addres中读取数据
  • 这里我们直接将内容打印
  • 如果读到了quit,就退出
代码

while (true){if (strcmp(addres, "quit") == 0){break;}cout << addres << endl;sleep(2);}

 

两端运行情况

 

共享内存特点

这里我们使用命名管道作为对比的例子,之后会使用管道来完善共享内存

拷贝次数少

管道的拷贝次数

  • 通过管道通信 -- 也就是创建两个文件作为管道的读端和写端
  • 当写入的时候,我们通过键盘输入,输入的数据先被拷贝到我们自己设定的缓冲区(也就是定义的数组)中,然后再被传输到管道文件中
  • 读出也是一样,先要从管道文件到设定的缓冲区,再打印出来,而打印也就是将数据传输到显示器上
  • 所以至少需要四次拷贝

   

共享内存的拷贝次数

  • 共享内存是直接在物理内存上开辟一块空间,然后映射到需要进行通信的进程的地址空间中
  • 写入的时候,输入的内容实际上是直接写入到共享内存中的,不需要经过自定义的缓冲区
  • 打印也同样,直接从共享内存中读出,然后显示到显示器上
  • 所以只需要两次

 

没有访问控制

管道

  • 前面已经操作过了,管道文件只有当双方同时打开时,才会开始通信,否则会阻塞
  • 写满 / 没有写,另一方会等待,而不是一直在读

共享内存

  • 没有任何的控制
  • 从前面的操作可以看到,其中一方的运行不需要依赖另一方
  • 只要写完一句,就直接会被读走
  • 即使没有写,也会一直读 
  • 这样就会导致并发问题
并发问题
  • 可能要传递的信息是很长的,但可能中途就会被服务端读走
  • 这样它就拿不到完整的数据,可能就会导致无法执行相应的操作

添加访问控制(通过管道)

因为管道是有访问控制的,所以可以借助管道,让共享内存也具有访问控制

代码
头文件
// 加入访问控制(通过管道来传递信号,接收到信号才进行读取)#define FIFO_PATH "./fifo"
#define READ O_RDONLY
#define WRITE O_WRONLY | O_TRUNCclass Init //让管道文件具有类的特性,出作用域自动释放
{
public:Init(){umask(0);int ret = mkfifo(FIFO_PATH, 0666);assert(ret == 0);(void)ret;log("fifo created success", notice) << endl;}~Init(){unlink(FIFO_PATH);log("fifo removed success", notice) << endl;}
};void wait_signal(int fd) //读取指定文件内容作为信号
{uint32_t signal = 0;log("waiting ...", notice) << endl;ssize_t size = read(fd, &signal, sizeof signal);assert(size == sizeof(uint32_t));(void)size;
}
void send_signal(int fd) //向指定文件写入signal
{uint32_t signal = 1;ssize_t size = write(fd, &signal, sizeof signal);assert(size == sizeof(uint32_t));(void)size;log("being awakened ...", notice) << endl;
}int open_fifo(string path, int flags) //以指定方式打开创建好的管道文件
{int fd = open(path.c_str(), flags);assert(fd >= 0);return fd;
}
void close_fifo(int fd)
{close(fd);
}
服务端
  • 创建管道文件
  • 等待客户端的信号(也就是等待管道文件中出现内容时)
  • 被唤醒后打印addres中的内容
//通信
// 添加访问控制Init init; // 创建管道文件int fd = open_fifo(FIFO_PATH, READ);while (true){wait_signal(fd); // 等待唤醒if (strcmp(addres, "quit") == 0){break;}cout << addres << endl;}close_fifo(fd); // 通信结束
客户端
  • 打开创建好的管道文件
  • 读取键盘输入内容,存入addres中
  • 成功输入时,向服务端发送信号(也就是向管道写入数据)
 // 添加访问控制int fd = open_fifo(FIFO_PATH, WRITE);while (true){ssize_t size = read(0, addres, SUM_SIZE - 1);if (size > 0){addres[size - 1] = 0; //处理回车符send_signal(fd);if (strcmp(addres, "quit") == 0){break;}}}

 

运行情况

只有一方时,阻塞在管道文件打开的位置:

当客户端接入后:

发送信息时,会将信号和数据都传递给对方:

退出:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/147920.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

神辅助 Cursor 编辑器,加入 GPT-4 让编码更轻松!

分类 互联网 在 ChatGPT 问世之前&#xff0c;我们的编码方式很多时候都是面向搜索引擎编码&#xff0c;需要不断地进行搜索&#xff0c;然后复制粘贴&#xff0c;俗称复制粘贴工程师。 但是&#xff0c;随着ChatGPT的出现&#xff0c;这一切将彻底改变。 ChatGPT 是一种基于…

AI工具合集

网站&#xff1a;未来百科 | 为发现全球优质AI工具产品而生 (6aiq.com) 如今&#xff0c;AI技术涉及到了很多领域&#xff0c;比如去水印、一键抠图、图像处理、AI图像生成等等。站长之家之前也分享过一些&#xff0c;但是在网上要搜索找到它们还是费一些功夫。 今天发现了一…

STM32 HAL库函数HAL_SPI_Receive_IT和HAL_SPI_Receive的区别

背景 前段时间开发一个按键板驱动&#xff0c;该板用的STM32F103系列单片机&#xff0c;前任工程师用STM32CubeMX生成的工程&#xff0c;里面全是HAL库调用&#xff0c;我接手后&#xff0c;学习了下HAL库的用法&#xff0c;踩坑不少&#xff0c;特别是带IT后缀的函数&#xf…

【左程云算法全讲11】贪心算法 并查集

系列综述&#xff1a; &#x1f49e;目的&#xff1a;本系列是个人整理为了秋招面试的&#xff0c;整理期间苛求每个知识点&#xff0c;平衡理解简易度与深入程度。 &#x1f970;来源&#xff1a;材料主要源于左程云算法课程进行的&#xff0c;每个知识点的修正和深入主要参考…

电子电器架构 —— 车载网关边缘节点总线转换

电子电器架构 —— 车载网关边缘节点路由转发策略 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 PS:小细节,本文字数3000+,详细描述了网关在车载框架中的具体性能设置。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 没有人关注你。也无…

系列十、你说你做过JVM调优和参数配置,请问如何盘点JVM系统的默认值?

一、JVM的参数类型 1.1、标配参数 java -versionjava -help 1.2、XX参数 1.2.1、Boolean类型 公式&#xff1a;-XX:或者- 某个属性值 表示开启、-表示关闭 # 是否打印GC收集细节 -XX:PrintGCDetails -XX:-PrintGCDetails# 是否使用串行垃圾收集器 -XX:UseSerialGC -XX:-UseS…

使用FFmpeg合并多个ts视频文件转为mp4格式

前言 爬取完视频发现都是ts文件&#xff0c;而且都是几百KB的视频片段&#xff0c;.ts 全名叫&#xff1a;MPEG Transport Stream&#xff0c;它是一个万能的多媒体容器&#xff0c;可以装下音频、视频、字幕。有时我们需要将.ts文件转换为其他更加广泛被支持的格式&#xff0…

springboot项目中没有识别到yml文件解决办法

springboot项目中没有识别到yml文件解决办法 ![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传] 1、这个意思就是没有配置数据库的数据源路径。所以需要配置数据源&#xff0c;比如mysql的驱动和路径。检查是否在properties或者yml文件中是否已经配置好。…

简单的用Python实现一下,采集某牙视频,多个视频翻页下载

前言 表弟自从学会了Python&#xff0c;每天一回家就搁那爬视频&#xff0c;不知道的以为是在学习&#xff0c;结果我昨天好奇看了一眼&#xff0c;好家伙&#xff0c;在那爬某牙舞蹈区&#xff0c;太过分了&#xff01; 为了防止表弟做坏事&#xff0c;我连忙找了个凳子坐下&…

图像分类(四) 全面解读复现GoogleNet_InceptionV1-V4

论文解读 InceptionV1 前言 论文题目: Going Deeper with Convolutions Googlenet论文原文地址:https://arxiv.org/pdf/1409.4842.pdf 之前看过VGG的论文&#xff08;VGG精读直达&#xff09;。当时VGG获得了 2014 ILSVRC 图像分类的第二名&#xff0c;今天来看一下第一名…

Yolov5

Yolov5 Anchor &#xff11;&#xff0e;Anchor是啥&#xff1f; anchor字面意思是锚&#xff0c;是个把船固定的东东&#xff08;上图&#xff09;&#xff0c;anchor在计算机视觉中有锚点或锚框&#xff0c;目标检测中常出现的anchor box是锚框&#xff0c;表示固定的参考框…

基于金鹰算法优化概率神经网络PNN的分类预测 - 附代码

基于金鹰算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于金鹰算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于金鹰优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络的光滑…

使用Qt实现多人聊天工作室

目录 1、项目背景 2、技术分析 3、架构设计 3、1 服务器架构 3.1.1 模块划分 3.1.2 模块之间的交互 3、2 客户端架构 3.2.1 模块划分 3.2.2 模块之间交互 4、实现过程 4、1 功能实现 4.1.1 用户登录注册功能​编辑 4.1.2 用户主界面功能 4、2 设计实现 4.2.1 登录…

关于Flume-Kafka-Flume的模式进行数据采集操作

测试是否连接成功&#xff1a; 在主节点flume目录下输入命令: bin/flume-ng agent -n a1 -c conf/ -f job/file_to_kafka.conf -Dflume.root.loggerinfo,console # 这个file_to_kafka.conf文件就是我们的配置文件 然后在另一台节点输入命令进行消费数据&#xff1a; kafka-cons…

SQL INSERT INTO 语句详解:插入新记录、多行插入和自增字段

SQL INSERT INTO 语句用于在表中插入新记录。 INSERT INTO 语法 可以以两种方式编写INSERT INTO语句&#xff1a; 指定要插入的列名和值&#xff1a; INSERT INTO 表名 (列1, 列2, 列3, ...) VALUES (值1, 值2, 值3, ...);如果要为表的所有列添加值&#xff0c;则无需在SQL…

超详细vue3选项式父子组件传值

一、问题背景 最近遇到了一个情景&#xff1a; 子组件干完事情&#xff0c;需要对父组件的变量进行更新&#xff0c;因为父组件将该变量传递给子组件&#xff0c;但是不会双向绑定&#xff0c;这时候我们就需要传值或者触发回调去解决这个问题 我们将分为两个部分 1.父组件传…

力扣hot100 两数之和 哈希表

&#x1f468;‍&#x1f3eb; 力扣 两数之和 &#x1f60b; 思路 在一个数组中如何快速找到某一个数的互补数&#xff1a;哈希表 O(1)实现⭐ AC code class Solution {public int[] twoSum(int[] nums, int target){HashMap<Integer, Integer> map new HashMap<&g…

【机器学习12】集成学习

1 集成学习分类 1.1 Boosting 训练基分类器时采用串行的方式&#xff0c; 各个基分类器之间有依赖。每一层在训练的时候&#xff0c; 对前一层基分类器分错的样本&#xff0c; 给予更高的权重。 测试时&#xff0c; 根据各层分类器的结果的加权得到最终结果。 1.2 Bagging …

基于世界杯算法优化概率神经网络PNN的分类预测 - 附代码

基于世界杯算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于世界杯算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于世界杯优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要&#xff1a;针对PNN神经网络…

python+appium+pytest自动化测试-参数化设置

来自APP Android端自动化测试初学者的笔记&#xff0c;写的不对的地方大家多多指教哦。&#xff08;所有内容均以微博V10.11.2版本作为例子&#xff09; 在自动化测试用例执行过程中&#xff0c;经常出现执行相同的用例&#xff0c;但传入不同的参数&#xff0c;导致我们需要重…