目录
共享内存的地位:
共享内存是Linux中最快的进程间通信方式,所以很多追求效率的程序之间进行通信的时候,都会选择共享内存
例如: 守护进程, 和被守护的进程 就要使用共享内存
一、共享内存的原理
- 1.1 在物理内存当中开辟一段空间
- 1.2不同的进程通过页表将物理内存空间映射到自己的进程虚拟地址空间当中
- 1.3不用的进程通过操作自己进程虚拟地址空间当中的虚拟地址,来操作共享内存(读或者写)
示意图如下:
二、共享内存的接口
1、创建或者获取共享内存的接口
int shmget(key_ t key, size_ t size, int shmflg) sh——>> share memory
参数:
- key;共享内存标识符(相当于人的身份证)
- size:共享内存大小
- shmflg:获取/ 创建共享内存时,传递的属性信息
- IPC_ CREAT :
- 如果获取的共享内存不存在,则创建
- IPC_ EXCL | IPC_ CREAT:
- 如果获取的共享内存存在,则函数报错
- 如果获取的共享内存不存在,则创建。
- 本质上:该组合是要要获取是重新创建的共享内存
- 按位或上权限,权限也是8进制数字(这里的权限是指,这块物理内存的共享区域的权限我们对这块区域内的执行权限)
- IPC_ CREAT :
- 返回值:
- 成功:返回共享内存操作句柄(要操作共享内存就需要这个操作句柄)
- 失败: -1
2、将共享内存附加到进程的虚拟地址空间
void *shmat(int shmid, const void *shmaddr, int shmflg) at ——>> attach
参数:
- shmid:
- 共享内存操作句柄
- shmaddr:
- 将共享内存附加到进程虚拟地址空间的共享区当中的哪一个地址上。
- 一般让操作系统自己分配,传递NULL
shmflg:以什么权限将共享内存附加到进程当中
- SHM_ RDONLY: 只读
- 0 :可读可写
- 返回值:
- 成功:返回附加的虚拟地址
- 失败:-1
3、分离
- int shmdt(const void *shmaddr);
- 参数:
- shmaddr: shmat的返回
- 返回值:
- 成功:0
- 失败:-1
4、操作共享内存接口
- int shmctl(int shmid,,int cmd, struct shmid_ds ,*buf);
- 参数:
- shmid:共享内存的操作句柄
- cmd:告诉shmct L函数需要完成什么功能
- IPC_ SET::设置共享内存属性信息 ,这个时候buf就是输入型参数,内容由程序员组织,传递给shmctl函数,并由他修改 共享内存的属性
- IPC_ STAT:获取共享内存属性信息 这时候buf就是出参,由shmctl函数进行填充
- IPC_ RMID :删除共享内存,第三个参 数传递NULL 即buf设置为NULL
三、代码验证共享内存
一个代码往共享内存中写,一个代码从共享内存中读
四、共享内存的特性
- 4.1生命周期跟随操作系统
- 4.2共享内存写的时侯是覆盖写的方式,在向共享内存中写入时,会先将共享内存中的内容清空,然后进行写入,
- 读的时候, 是访问地址,并没有将数据从共享内存中拿走。(异于管道)
4.3共享内存的删除特性
- 4.3.1 ipcs命令 & ipcrm 命令
我们可以通过ipcs命令来查看共享内存的信息
ipcrm命令:
可以通过 ipcrm -m [操作句柄]来删除一个共享内存
- 一旦共享内存被删除掉之后,共享内存的在物理内存当中的空间被销毁了
- 如果删除的共享内存的时候,共享内存附加的进程数量为0,则内核当中描述该共享内存的结构体也被释放了
如果删除的共享内存的时候,共享内存附加的进程数量不为0,则会将该共享内存的key,变成0x00000000。表示当前共享内存不能被其他进程所附加,共享内存的状态会被设置为destory。附加的进行一旦全部退出之后,该共享内存在内核的结构体会被操作系统释放掉