进程间通信(中)

一、什么是共享内存

共享内存实质是一块物理内存,多个进程通过将同一块物理内存映射到自己的虚拟地址空间,通过自己的虚拟地址空间访问这块物理内存,实现进程间数据共享。

二、如何使用

具体流程:
1.创建共享内存
接口:int shmget(key_t key,size_t size,int shmflg);
在这里插入图片描述
功能:创建一个共享内存。
返回值:成功创建返回共享内存的操作句柄(非负整数),失败返回-1。
key_t key:共享内存的标识符(多个进程可以通过相同的标识符访问同一块共享内存,实现数据共享)。
size_t size:共享内存大小。
int shmflg:对共享内存的操作方式(IPC_CREAT表示不存在就创建共享内存,IPC_EXCL表示共享内存存在,则报错返回)。并且在创建过程中还要表明共享内存的操作权限。
举例:
在这里插入图片描述

2.映射共享内存到进程虚拟地址空间
接口:void * shmat(int shmid,const void * shmaddr,int shmflg);
在这里插入图片描述
功能:将共享内存映射到进程的虚拟地址空间。
返回值:映射成功,返回实际映射在虚拟地址空间的起始地址,失败返回(void*)-1。
int shmid:共享内存的操作句柄(也就是shmget接口的返回值)。
void * shmaddr:虚拟地址空间中的映射首地址(NULL表示操作系统自己分配要映射到虚拟地址空间的某个位置)。
int shmflg:对共享内存的操作。(SHM_RDONLY表示只读,0表示可读可写)
举例:
在这里插入图片描述对于以上程序,如果不睡眠,就得不到映射连接数为1,因为进程不睡眠就会退出,进程退出后,该进程的虚拟地址空间也会被回收。而当我们结束睡眠,映射连接数也就自然变为0。
3.内存操作
因为上边返回的是共享内存映射到虚拟地址空间的首地址,所以就可以通过memcpy等接口在共享内存中进行数据的读写,在这里就不多说了。
4.解除映射关系
接口:int shmdt(const void * shmaddr);
在这里插入图片描述
功能:解除虚拟地址空间与共享内存的映射关系。
返回值:成功解除返回0,失败返回-1。
const void * shmaddr:虚拟地址空间的映射首地址。
举例:
在这里插入图片描述
5.删除共享内存
接口:int shmctl(int shmid,int cmd,struct shmid_ds * buf);
在这里插入图片描述
功能:删除共享内存。
这里需要注意的是,每个共享内存都会有一个映射连接数(表示当前共享内存与多少进程建立的映射关系),共享内存只有在映射连接数为0时才可以被删除,如果当前不为0,则从当前开始,拒绝后续的所有映射请求,直到映射连接数为0时被删除。
返回值:仅对于删除操作而言,成功删除返回0,失败返回-1。(不同操作,返回值不同,大家可以自己深入研究)
int shmid:共享内存的操作句柄。
int cmd:对共享进行的操作方式(这里删除使用IPC_RMID)
struct shmid_ds * buf:主要用于获取共享内存的信息(删除操作,不需要去获取,所以通常置NULL即可)。
举例:
在这里插入图片描述
通过事例可以看出,3秒之前进程的虚拟地址空间与创建的共享内存进行了映射连接,所以映射连接数为1,而当3秒之后,解除了映射连接,这是映射连接数变为了0,并且这时因为映射连接数为0,所以在删除共享内存时,就直接删除了。

三、特性与注意事项

3.1 特性:

1.共享内存是最快的一种进程间通信的方式。(不需要进行内核态和用户态之间的数据拷贝)。
2.生命周期随内核。

3.2 注意事项

1.共享内存有可能会被多个进程进行访问,容易造成数据交叉或者被覆盖的危险。
2.共享内存需要去进行互斥和同步对其进程间通信进行保护。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值