文章目录
- 序言
- shm 原理
- 对shm的理解
- 通过代码认识shm
- 调用shmget方法实现
序言
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所维护
创作不易,有用请观众姥爷来个三连支持一下~~~