Linux 进程通信--共享内存


前言

管道的通信中:涉及两次用户态与内核态之间的数据拷贝;将数据写入管道,从管道读取数据
共享内存的通信:直接通过虚拟地址访问物理内存实现共享内存中的数据操作
相较于管道通信少了两次用户态与内核态之间的数据拷贝操作,因此速度快

一、共享内存

共享特性:
特性:共享内存是最快的进程间通信方式
本质原理:在物理内存上开辟一块内存空间,多个进程可以将同一块物理内存空间映射到自己的虚拟地址空间,通过自己的虚拟地址直接访问这块空间,通过这种方式实现数据共享.

共享内存的生命周期随内核,在物理内存开辟空间,信息存储在内核;共享内存是属于内核的一个进程间通信资源;不会随着进程的退出而释放;内核重启会释放或者手动释放.

共享内存:
在这里插入图片描述

二、共享内存的操作流程:

1.创建共享内存–在物理内存上开辟空间
2.进程将共享内存映射到自己的虚拟地址空间
3.基本的内存操作都可以对这块空间进行操作
4.解除虚拟地址空间与共享内存的映射关系
5.释放共享内存资源

1.创建共享内存:int shmget(key_t key,size_t size,int shmflg);

key:内核中共享内存的标识符—多个进程通过相同的标识符才能打开同一个共享内存
size:共享内存大小——以内存页(4096字节)为单位进行分配
shmflg:IPC_CREAT-存在则打开,不存在则创建| IPC_EXCL与IPC_CREAT同时使用,若存在报错,不存在则创建 | mode
返回值:返回一个非负整数—共享内存的操作句柄;失败返回-1;
//生成一个key值:key_t ftok(const char* pathname,int proj_id);–通过inode节点号与projid合成一个key
举例:
在这里插入图片描述

2.建立映射连接:void shmat(int shmid,const voidshmaddr,int shmflg)

shmid:shmget返回的共享内存操作句柄
shmaddr:共享内存映射在虚拟地址空间中的首地址–通常置为NULL(让操作系统来为我们选择合适的)
shmflg:映射成功之后对共享内存可以进行的操作 SHM_RDONLY用于只读(前提是有读的权限)/ 0-默认可读可写
返回值:返回共享内存映射在虚拟地址空间中的首地址–通过这个首地址进行后续的内存操作 失败返回(void*)-1
举例:
在这里插入图片描述

3.解除映射关系:int shmdt(const void*shmaddr)

shmaddr:映射在虚拟地址空间中的首地址
成功返回0;失败返回-1;
在这里插入图片描述

4.删除共享内存:shmctl(int shmid,int cmd,struct shmid_ds *buf);

shmid:共享内存操作句柄
cmd: 对共享内存想要进行的操作 IPC_RMID删除共享内存
buf:用于获取/设置共享内存信息的结构,不使用则置空NULL
成功返回0,失败返回-1;

举例:
在这里插入图片描述

共享内存删除的时候,并不会立即被删除,只是将其状态置为被销毁状态,移除标识–为了不让这个共享内存继续被其他进程映射连接,然后等到当前共享内存映射连接数为0的时候,才会真正删除这块共享内存。
在这里插入图片描述

操作系统中进程间通信资源的命名操作:
ipcs:查看进程间通信资源
-m 查看共享内存
-q 查看消息队列
-s 查看信号量
ipcrm:删除进程间通信资源
-m

在这里插入图片描述
链接: 共享内存的读端代码.
链接: 共享内存的写端代码.

三、消息队列:(只讲原理)

内核中的优先级队列;多个进程通过访问同一个队列;进行添加节点或者获取节点实现通信

1.创建消息队列–在内核中创建一个优先级队列 int msgget(key_t key,int msgflg);
2.进程可以向队列中添加节点/获取节点
在这里插入图片描述

3.删除消息队列 int msgctl(int msqid,int cmd,struct msqid_ds *buf);

特性:
1.自带同步与互斥
2.生命周期随内核

四、信号量

是用于实现进程间的同步与互斥的(共享内存本身是不提供同步与互斥的,操作存在安全,因此需要用信号量保护对其共享内存的操作
同步:通过条件判断实现临界资源访问的合理性
互斥:通过同一时间的唯一访问实现临界资源访问的安全性
本质:一个内核中的计数器+pcb等待队列

举个例子:
停车场----告示牌–计数器–统计停车场中空闲车位的数量
假如我有车,去停车场停车,通过告示牌计数器判断是否有空闲车位。
如果有就停车,停车后计数器-1;
如果没有停车位,就等着,直到通知我可以去停车
信号量这个计数器可以对数据资源进行计数,进程在访问资源之前,先通过计数判断能够访问资源。
计数>0才能访问,获取一个资源,计数-1;
计数<=0不能访问,计数-1;然后将pcb状态置为可中断休眠状态,加入等待队列;其他进程产生了资源,计数+1,若计数器>0则什么也不干,若计数器<0则从对列中唤醒一个pcb去获取资源

同步:资源能访问的时候,让你访问;不能访问的时候,让你等着;等到能够访问了再去唤醒你去访问
信号量通过自身的计数器+等待队列 以及 使一个进程等待以及唤醒一个进程的操作组成

信号量实现互斥:保证同一时间只有一个进程能够访问资源
只需要保证信号量的资源计数不会大于1就可以实现
假设有一个停车位-计数为1
我的车停车则-1,变为0;其他的车就都无法停车;我的车出来了则+1

信号量实现互斥的思想:以资源只有一份,只有一个进程能够获取;用完了放回来;下一个进程再获取的思想

信号量的本质:计数器+等待队列+使进程等待/唤醒的接口
同步的实现:
通过计数器对资源进行计数;计数>0表示能获取;计数<=0表示不能获取通过等待接口使进程等待加入等待队列;等到有资源的时候唤醒
互斥的实现:
通过保证计数器不会大于1,保证同一时间只有一个进程能够访问资源

总结

共享内存:
本质原理:多个进程将同一块物理内存映射到自己的虚拟地址空间实现数据共享
特性:
1.最快的进程间通信方式
2.生命周期随内核
注意:共享内存并没有自带同步与互斥—多个进程进行访问的时候存在安全问题
操作:代码操作流程/具体的接口+命令操作ipcs/ipcrm

进程间通信是什么–为什么
进程间通信方式的种类:管道/共享内存。消息队列/信号量
每一种通信方式都要能够保证能够掌握:本质原理;特性;实现流程

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值