共享内存:
共享内存区是最快的IPC形式,不需要像管道那样复制来复制去的。⼀旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递 不再涉及到内核,换句话说是进程不再通过执⾏进⼊内核的系统调⽤来传递彼此的数据。
共享内存的类型
Linux支持两种主要类型的共享内存:
System V 共享内存:传统方法,使用
shmget
、shmat
等系统调用。POSIX 共享内存:更现代的方法,基于文件描述符,使用
shm_open
、mmap
等函数。
共享内存的管理
因为可能同时存在多个进程在使用不同的共享内存。
管理的方式还是先描述再组织。所以说一定要有对应描述共享内存的结构体。
使用共享内存的接口
int shmget(key_t key,size_t size,int shmflag)
key(表示共享内存的唯一性,但是应该注意这个key不是内核形成的,而是在用户层通过函数传共过去的):所以说创建的这个共享内存对应的结构体中一定有这个key值。
size:共享内存的大小
shmflag:1.IPC_CREAT如果该共享内存不存在就创建,否则就打开并返回
2.IPC_EXCL单独使用没有用意义,只有跟IPC_CREAT组合使用表示如果该shm不存在就创建,否则就出错返回。
所以只要使用后面两个参数的shmget函数返回成功就说明该共享内存一定是刚刚创建的新的共享内存。另外这个参数还能进行权限的设置,共享文件在操作系统中也被认为为文件。
void* shmat(int shmid,const void* shmaddr,int shmflg);这个函数就是将指定的共享内存挂接到指定的进程的虚拟地址空间中并返回这个虚拟地址;shmaddr虚拟地址,从指定的虚拟地址开始挂接,这个参数一般都是nullptr因为进程的虚拟地址空间操作系统自己是最清楚的,我们不能盲目的指定;shmflg是指定共享内存的权限的,给0就是使用默认设置。
共享内存的特点
映射之后读写直接被进程双方看到,不需要进行任何的系统调用获取或者读写内容,所以速度很快。通信双方没有所谓的同步机制,没有对共享内存中数据的保护。
共享内存的大小在创建的时候一定是4KB的整数倍, 内核中的共享内存大小一定是4KB的整数倍,但是你申请的大小是你能使用的大小。比如你申请4097B实际上给你开辟了4096*2B但是你只能使用4097B的大小
删除共享内存
创建的共享内存如果没有删除那么内存共享资源就会一直存在(即使进程已经结束,除非重启操作系统,共享内存的生命周期是随内核的)。这一点跟文件有所不同,文件会在检测到引用计数为0时自动关闭,文件的生命周期是随进程的。
在删除共享内存时是不能使用key的值来指定共享内存,而是通过shmid来指定。key未来只是给内核来区分唯一性的。因为指令是用户级别的,不是内核级别的。