进程间通信之共享内存

一、共享内存实现进程间通信的原理

共享内存实际是操作系统在实际物理内存中开辟的一段内存。

共享内存实现进程间通信,是操作系统在实际物理内存开辟一块空间,一个进程在自己的页表中,将该空间和进程地址空间上的共享区的一块地址空间形成映射关系。另外一进程在页表上,将同一块物理空间和该进程地址空间上的共享区的一块地址空间形成映射关系。 ​ 当一个进程往该空间写入内容时,另外一进程访问该空间,会得到写入的值,即实现了进程间的通信。

要实现进程间通信需要两个进程看到同一块空间,系统开辟的共享内存就是两个进程看到的同一资源。

注意:共享内存实现进程间通信是进程间通信最快的。

二、管理共享内存的数据结构

共享内存实现进程间通信不只仅限于两个进程之间,可以用于多个进程之间。并且系统中可能会有多个进程在进行多个通信。所以系统需要将这些通信的进程管理起来。如果不管理,操作系统怎么知道这块共享内存挂接了哪个进程等信息。

如何管理?就是先描述再组织。

描述共享内存的数据结构里保存了一个ipc_perm结构体,这个结构体保存了IPC(进程将通信)的关键信息。

/* Obsolete, used only for backwards compatibility and libc5 compiles */
struct ipc_perm
{__kernel_key_t  key;//共享内存的唯一标识符__kernel_uid_t  uid;__kernel_gid_t  gid;__kernel_uid_t  cuid;__kernel_gid_t  cgid;__kernel_mode_t mode; //权限unsigned short  seq;
};

其中key是共享内存的唯一标识。

三、共享内存函数

1、ftok函数

作用:是算出一个唯一的key值返回。

参数:第一个是地址,第二个是至少8为的项目id,不能为0,两参数可以是任意值,但是要符合格式。

返回值:ftok如果成功返回一个key值,如果失败返回-1。如果失败了再重新填写参数即可。

ftok中的参数可以随便填写,但是要符合格式,ftok只是利用参数,再运用一套算法,算出一个唯一的key值返回。这个key值可以传给共享内存参数,作为struct ipc_perm中唯一标识共享内存的key。

#define PATHNAME "."
#define PROJID 0x3456
​
const int gsize=4096;//暂时
​
key_t getKey()
{key_t k=ftok(PATHNAME,PROJID);if(k == -1){cerr << "error: " << errno << " : " << strerror(errno) << endl;exit(1);}return k;
}
2、shmget函数

参数:

key:为共享内存的名字,一般是ftok的返回值。

size:共享内存的大小,以page为单位,大小为4096的整数倍。 shmflg:权限标志,常用两个IPC_CREATIPC_EXCL,一般后面还加一个权限,相当于文件的权限。

IPC_CREAT:创建一个共享内存返回,已存在打开返回

单独使用IPC_CREAT: 创建一个共享内存,如果共享内存不存在,就创建之,如果已经存在,获取已经存在的共享内存并返回

IPC_EXCL不能单独使用,一般都要配合IPC_CREAT

IPC_CREAT | IPC_EXCL: 创建一个共享内存,如果共享内存不存在,就创建之, 如果已经存在,则立马出错返回 -- 如果创建成功,对应的shm,一定是最新的!

返回值:

成功返回一个非负整数,即共享内存的标识码,失败返回-1。

为什么已经有一个key来标识共享内存,还需要一个返回值来标识共享内存?因为key是内核级别的,供内核标识,shmget返回值是用户级别的,供用户使用的。

代码:

int createShmHelper(key_t k, int size, int flag)
{int shmid=shmget(k,gsize,flag);if(shmid == -1){cerr << "error: " << errno << " : " << strerror(errno) << endl;exit(2);}return shmid;
}
int createShm(key_t k,int size)//用于server
{umask(0);int s_value=createShmHelper(k,size, IPC_CREAT|IPC_EXCL|0666);return s_value;
}
​
int getShm(key_t k,int size) //用于client
{int c_value=createShmHelper(k,size,IPC_CREAT);return c_value;
}

当我们执行两次程序,第一次没有报错,即是成功创建了一个共享内存,而第二次执行就报错了,报错信息是文件已存在。

这是因为我们在进程中创建了一个共享内存,但是我们执行程序的时候共享内存还在,但是我们没有释放共享内存,所以就会报错。

这里得出一个结论:IPC(进程将通信)资源生命周期不随进程,而是随内核的,不释放会一直占用,除非重启。所以,shmget创建的共享内存要释放掉,不然会内存泄漏。

可以用ipcs -m来查看共享内存。

可以用命令行来释放共享内存:

ipcrm -m shmid(shmget返回值)
3、shmctl函数

用命令的方法删除太麻烦了,我们也可以用shmctl函数直接进行删除。

函数功能:管理对共享内存的控制

参数:

shmid:共享内存标识符

cmd:

IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中

IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode复制到共享内存的shmid_ds结构内

IPC_RMID:删除这片共享内存

buf: 共享内存管理结构体。具体说明参见共享内存内核结构定义部分

代码:

void delShm(int shmid)
{int n = shmctl(shmid, IPC_RMID, nullptr);if(n==-1){cerr << "error: " << errno << " : " << strerror(errno) << endl;exit(3);}(void)n;
}
4、shmat函数, shmdt函数

void *shmat(int shmid, const void *shmaddr, int shmflg)

作用:使创建的共享内存与调用该函数进程的进程地址空间参数相关联

shmid共享内存标识符
shmaddr指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核自己决定一个合适的地址位置
shmflgSHM_RDONLY:为只读模式,其他为读写模式

注意:shmaddr为空的话,shmflg设为0。

int shmdt(const void *shmaddr)

作用:与shmat函数相反,是用来断开与共享内存附加点的地址,禁止本进程访问此片共享内存

shmaddr:连接的共享内存的起始地址

char* attachShm(int shmid)
{char *start = (char*)shmat(shmid, nullptr, 0);return start;
}
​
void detachShm(char *start)
{int n = shmdt(start);assert(n != -1);(void)n;
}

每隔一秒循环打印共享内存的写法:

while :;do ipcs -m ; sleep 1;done

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

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

相关文章

数字孪生场景渲染能力中的WebGL技术路线

使用三维建模技术构建出的虚拟现实场景后&#xff0c;需要通过渲染引擎实现场景的高精度、高保真和实时渲染。同时&#xff0c;需要将现实场景中的数据信息融合到虚拟场景中&#xff0c;实现对现实情况的监测和控制。 目前大多数数字孪生城市项目在三维渲染引擎的技术选型上通…

测试工程师首chatGPT,编写python读取xmind测试用例chatgtp+python+xmind

背景 有用xmind写测试用例的吧&#xff0c;统计一个xmind的条&#xff0c;需要花大量的时间&#xff0c;还有要统计有多少条冒烟的&#xff0c;多少条不通过的&#xff0c;还有通过的条数。 需求 快速使用python&#xff0c;写一个简单的脚本&#xff0c;统计所有xmind节点&…

c++ 内存管理一:初识内存分配工具

文章目录 前言1 new 和 delete2 new[]和delete[]3 operator new4 placement new5 malloc和free6 allocator 前言 侯捷 c内存管理学习总结笔记。 在C中&#xff0c;有几种常用的内存分配工具可以帮助进行动态内存管理。 从c应用程序自上而下&#xff0c;通常会有这样的几种分配…

算法分析基础题目

第一章-算法概述 递归算法必须具备的两个条件是边界条件或停止条件和递推方程或递归方程冒泡排序时间复杂度是___&#xff0c;堆排序时间复杂度是___。 O ( n 2 ) O(n^2) O(n2), O ( n l o g n ) O(nlogn) O(nlogn)斐波那契数列的第1项为1&#xff0c;第2项为2&#xff0c;以…

[RocketMQ] Producer发送消息的总体流程 (七)

单向发送: 把消息发向Broker服务器, 不管Broker是否接收, 只管发, 不管结果。同步发送: 把消息发向Broker服务器, 如果Broker成功接收, 可以得到Broker的响应。异步发送: 把消息发向Broker服务器, 如果Broker成功接收, 可以得到Broker的响应。异步所以发送消息后, 不用等待, 等…

LLaMA模型微调版本:斯坦福 Alpaca 详解

项目代码&#xff1a;https://github.com/tatsu-lab/stanford_alpaca 博客介绍&#xff1a;https://crfm.stanford.edu/2023/03/13/alpaca.html Alpaca 总览 Alpaca 是 LLaMA-7B 的微调版本&#xff0c;使用Self-instruct[2]方式借用text-davinct-003构建了52K的数据&#x…

vue3框架开发uniapp高仿度小满金融App项目

vue3框架开发uniapp高仿度小满金融App项目 心血来潮写了度小满前端项目使用vue3开发地址&#xff1a;度小满金融 下面是实现效果

第一次安装cocoapods经历

先是执行&#xff1a;sudo gem install cocoapods 报错&#xff1a; ERROR: Error installing cocoapods: The last version of activesupport (> 5.0, < 8) to support your Ruby & RubyGems was 6.1.7.3. Try installing it with gem install activesupport -v…

CSS 备忘录2-动画、渐变、颜色、选择器等

1、背景 background属性是八个属性的简写形式&#xff1a; background-image 指定一个文件或生成的颜色渐变作为背景图片background-position 设置图片的初始位置background-size 指定背景图片的渲染尺寸background-repeat 是否平铺图片ba…

智能相机的功能介绍

智能视觉检测相机主要是应用在工业检测领域图像分析识别、视觉检测判断。相机具有颜色有无判别、颜色面积计算、轮廓查找定位、物体特征灰度匹配、颜色或灰度浓淡检测、物体计数、尺寸测量、条码二维码识别读取、尺寸测量、机械收引导定位、字符识别等功能。相机带有HDMI高清视…

Java版企业电子招投标系统源码 Spring Cloud+Spring Boot 电子招标采购系统功能清单

一、立项管理 1、招标立项申请 功能点&#xff1a;招标类项目立项申请入口&#xff0c;用户可以保存为草稿&#xff0c;提交。 2、非招标立项申请 功能点&#xff1a;非招标立项申请入口、用户可以保存为草稿、提交。 3、采购立项列表 功能点&#xff1a;对草稿进行编辑&#x…

电脑键盘点击记录

这里写自定义目录标题 通过敲击键盘&#xff0c;记录键盘按键&#xff0c;并记录下来&#xff0c;保存在电脑一个路径下&#xff0c;txt文档格式记录 通过敲击键盘&#xff0c;记录键盘按键&#xff0c;并记录下来&#xff0c;保存在电脑一个路径下&#xff0c;txt文档格式记录…