探索共享内存:解锁并发编程的潜力

19 篇文章 0 订阅

序言

system V版本
指定的一种规则(俗话说一流公司定规则,二流公司重服务,三流公司重技术).这个规则虽然有很多种(消息队列,共享内存等只是比较出名的几个).但是在内核的相关技术解决上是类似的,因为都是基于同一套标准

shm 原理

它是进程间通信的前提,必须让不同的进程看到同一份资源(这份资源由OS提供)

以父进程创建子进程为例:
在这里插入图片描述

对shm的理解

上述两个进程被加载进内存,共享同一块内存
但实际内存中,并不只存在这一对父子进程,还有其他的进程也有共享内存,所以在OS中会存在一张共享内存管理表
对上述内容的理解:
1.往后对共享内存的管理就变成了对数据结构的增删查改
在这里插入图片描述

2.共享内存具有唯一的标识,来保证第二个参与共享内存的进程看到的就是期望的那个共享内存---->怎么确定这个标识?怎么给另一个进程?
1.实现一个共享内存创建
利用shmget()函数实现在这里插入图片描述这个第一个参数类型,第一个参数代表什么意思呢?

ftok函数约定生成一个key_t的数,key_t本质是int

shmflg 即能创建,又能获取:
提供两个宏
IPC_CREAT:shm不存在,就创建,存在就获取并返回,只是读取设置0也可以(一般用于获取)
IPC_EXCL:不单独使用
IPC_EXCL | IPC_CREAT:shm 不存在就创建,存在就出错返回(一般用于创建)(主要是保证创建的共享内存是全新的)

2.识别给另一个进程 at—>attach
在这里插入图片描述

3.去掉进程的共享内存关联dt —> detach
在这里插入图片描述
页表映射部分的函数
通过页表将虚拟地址空间和物理内存的共享区进行映射

这个函数的第二个参数:

指定虚拟内存地址,但是不了解实际使用情况,所以一般为NULL

第三个参数:

不深究(实际表示写还是读,但是由权限码来控制),设为0即可

应用:

在这里插入图片描述运行查看结果:
在这里插入图片描述在sleep(5)看到了这个共享内存被server这个程序使用,所以被使用的进程数为1
当sleep结束后,程序退出,被调用进程数量就回到了0

怎么去掉这个关联的共享内存(本质就是修改页表)?
参数就是shmat的那个返回值
在这里插入图片描述
去除关联
从进程的地址空间中删除
此外,这个函数的返回值是返回一段地址空间,类似malloc的返回值

4.控制这个接口(改和查)

在这里插入图片描述
cmd参数:要做哪方面的控制,他提供了几个宏,其中使用演示:IPC_RMID(删除)
struct shmid_ds *buf参数:是OS的共享内存结构返回给上层用户的一个struct,暂时不用,设置为0

在这里插入图片描述

通过代码认识shm

通过写代码的认识共享内存

所有的 进程间通信,只有匿名管道是只允许血缘关系的进程间通信,其他进程间通信都是两个不相干进程间就能实现通信

首先两个进程之间怎么找到这个共享内存?

约定一个数字假设是1234,将这个1234在创建共享内存时就加载到struct shm结构体当中,未来要找这个共享内存只需要找这个对应的数字即可
这个数字可能与系统的共享内存的数字 冲突,所以利用内置的算法函数生成一个较低概率的数字

在这里插入图片描述ftok的演示结果
在这里插入图片描述
以下是源码:
在这里插入图片描述在这里插入图片描述
这个key是自己约定出来的

调用shmget方法实现

1.开辟共享内存,2.将shmid存入结构体内
在这里插入图片描述
结果:
在这里插入图片描述

可以看到不存在就创建全新的共享内存,存在就出错返回,(client,server里面是生成同一个shmid)
使用ipcs -m查看创建的共享内存

在这里插入图片描述
结论:

共享内存(IPC资源)的生命周期是随内核的

如何进行删除共享内存?

首先理解一下shmid和key的区别?
key只用来标识共享内存的唯一性
shmid用来操作这个共享内存
删除共享内存:
ipcrm -m shmid号

在这里插入图片描述
转16进制的方法:
在这里插入图片描述

sizeof(buf)用于限制 snprintf 函数写入数据的最大长度,以保证程序的安全性

cliet.cc
在这里插入图片描述
server.cc
在这里插入图片描述
两个进程如何知道他们在访问同一块内存?在命名管道是通过绝对路径看到同一份资源,在共享内存时通过key看到同一份资源
特殊性:共享内存没有同步机制,
由用户自己提供同步机制,(以前学过的管道实现)
server部分:
创建管道,打开管道,从管道读取
client:
打开管道,向管道内写入
在这里插入图片描述
如何,移除共享内存中的内容
对于共享内存中的数据,不需要进行实际的删除,让读的数据读完向后走,不在再能访问这个位置,就当是删除了
在这里插入图片描述
调整代码实现退出客户端和服务端后删除共享内存
unlink删除指定的文件:

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

1.共享内存是裸露给所有的使用者的,一定要注意安全问题
2.共享内存是所有进程间通信最快的方式
3.共享内存可以提供较大的空间

在这里插入图片描述
场景应用,共享内存相比较管道,少了几次拷贝?

首先数据会进入管道,通过write函数进入管道,再从管道通过read函数进入目标进程的缓冲区.
而共享内存会省去这两步,直接通过A—>共享内存---->B的过程

IPC_STAT的使用

创建关联的时间戳

能获取这个属性,意味着一定维护(描述)了这个共享内存
即:为什么能找到同一块共享内存,他们被OS所维护

创作不易,有用请观众姥爷来个三连支持一下~~~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

温有情

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值