一、共享内存
1、直接原理
进程间通信的本质是:先让不同的进程,看到同一份资源!!
我们要把这句话奉若圭臬一般
到了共享内存了支持双向通信能读也能写,但是一般都是一个读一个写
要想通信先看到同一个份资源,则
OS帮助申请内存,通过页表挂接到进程地址空间中,给应用层返回起始虚拟地址
如果要释放共享内存:先去关联,再释放共享内存
上面的操作都是进程直接做的吗?不是。直接由操作系统来做。
因为不能让进程直接malloc,你这样申请了那这块空间就是你的,会破坏了进程的独立性
所以必须利用系统调用,这样创建出来的共享内存就不属于进程私有的
操作系统要不要管理所有的共享内存呢??先描述,在组织
内核结构体描述共享内存,就得有结构体,这个共享内存多大,谁申请的,当前几个进程和我关联…
然后把所有的结构体用链表数组管理起来
所以在OS层面上,对共享内存的管理行为,变成对某种数据结构的增删查改
接下来要学习共享内存,要么就应用层面上学,系统调用接口搞懂
往底层学,就要找对应的先描述在组织是怎么做的!
在释放共享内存时,为什么先去关联,再释放共享内存?
因为共享内存的管理属性结构体中同样也维护了这块内存的引用计数,有多少个进程引用了它
万一别的进程还在引用着你难道直接释放吗?不可能
所以利用属性中引用计数,让引用计数–,等引用计数–到0在释放
共享内存的这块物理内存只是单纯保存数据,引用计数放在属性结构体中
2、直接代码
在物理内存中的这块共享内存呢,如果有人创建出来了,别人下一次就不需要再创建了直接获取就行了
也就会有如何创建,如何获取的概念
系统调用接口shmget
OS中会有很多共享内存,你怎么保证让不同的进程看到同一个共享内存呢??
shmget参数中的key,有进程用这个key创建,你拿着这个key去OS中 的共享内存中去获取,找到了那你们两个不就看到的是同一个内存吗
所以谈谈key:
1.key是一个数字,这个数字是几,不重要。关键在于它必须在内核中具有唯一性,能够让不同的进程进行唯一性标识
2.第一个进程可以通过key创建共享内存,第二个之后的进程,只要拿着同一个key就可以和第一个进程看到同一个共享内存了!
3.对于一个已经创建好的共享内存,key在哪?key在共享内存的描述对象中!
4.第一次创建的时候,必须有一个key了。怎么有?
利用算法ftok来生成一个冲突率小的key
这个Key值干嘛那么费劲让用户去设置,设置完成还有可能出现冲突,让OS生成一个key行不行?
OS不清楚哪个进程和哪个进程要通信,只有用户最清楚
这个key如果第一次创建共享内存由OS生成,并且我这个进程也拿到了key,但是另一个进程怎么知道对应的共享内存的key是多少呢?那有人说你把这个key传给另一个进程不就行了,可是我们正在解决的就是进程间通信的问题,这不就鸡生蛋,蛋生鸡了吗
所以与其说key由用户自由指定,不如说用户约定的,只要他们两个约定了同一个key,OS有属性Key相同的共享内存,那他们两个进程一定能找到
所以不需要系统随机指定key,因为系统随机不解决把这个key传递给另一个进程的目的,我们通过约定的方式让他们两个形成同一个key。所以必须由用户层下达给OS
pathname 和 proj_id让那几个进程看到,那哪几个进程就能通信!
- key —类似----路径---- 唯—
Key vs shmid
key也就是在创建时用,往后就都不用了,控制共享内存都用shmid
key是给OS用的
共享内存标识符shmid是用户层用它控制共享内存的
现象
创建共享内存的进程退了,可是利用
ipcs -m 查OS共享内存发现 共享内存仍然存在
说明
共享内存的生命周期是随内核的!
用户不主动关闭,共享内存会一直存在。
除非内核重启(用户释放)
因为你通完信走了,如果关闭了,上面还有数据的话,下次还想用就用不了了。
所以创建好一直存在,你想用就挂接,不用用户直接释放(ipcrm -m)
那释放用key还是shmid呢?
一定是shmid,因为命令行也属于用户层并不属于OS,key是给OS用的
3、共享内存的特性,扩展代码