56-System V 共享内存-shmat 与 shmdt

在理解内核对象后,接下来谈谈 System V 共享内存的 shmat 和 shmdt 函数。

1. shmget 函数

再次回顾一下 shmget 函数。

图1 中左侧表示的是一个进程空间(未区分内核空间与用户空间),进程空间中并非所有的线性地址被分配(或者说并非所有线性地址都被映射到物理页),黑色部分表示的是未分配的线性地址。


这里写图片描述
图1 进程空间与物理页

当你使用 shmget 创建出共享内存后,系统就会为你分配一个(或多个)物理页,具体分配多少,就看你当时使用 shmget 第二个参数指定的大小了,一般来说,至少会分配一个物理页(4KB 大小)。分配完成后,操作系统就会在 System V 共享内存的内核对象里进行记录。

2. shmat 与 shmdt

2.1 shmat 与 shmdt 函数原型

void *shmat(int shmid, const void *shmaddr, int shmflg);
int shmdt(const void *shmaddr);

2.2 shmat 函数原理

刚刚分配完物理页后,当然无法直接使用,因为没有任何线性地址映射到这个物理页,所以 shmat 函数就是干这个事的,它从进程空间中选择一个合适的或者你自己指定的线性地址(根据 shmat 第二个参数是否为0来决定,如果是0,系统自动选择),将其挂接到共享内存物理页上。图2 展示了将线性地址挂接到物理页的过程。

shmat 全称是 share memory attach,中译为共享内存挂接。


这里写图片描述
图2 shmat 函数将线性地址挂接到物理页

shmat 函数完成挂接后会返回那个位置的线性地址,这时候,用户就可以往这里存取数据了。shmat 的第三个参数,shmflg 用来控制读写权限,如果指定为 0,表示可读写,如果指定为 SHM_RDONLY,表示只读。还有其它的标志位,这是针对第二个参数不为 0 的情况所设计的,所以这里就不讨论了。

如果你理解了这个过程,shmdt 自然就解惑了。它所做的操作只是和 shmat 相反罢了。

注意:当你使用 shmdt 断开线性地址到物理地址的映射关系后,不能再次 shmat。再次 shmat 后虽然可以成功获取地址,但是强行读写会产生 segment fault. 具体原因尚不明确。有资料说是 shmdt 后会同时导致当前进程的拿到的 ipc 内核对象 id 无效化。

3. 总结

  • 理解共享内存大致实现原理
  • 理解 shmat 与 shmdt 干了什么

如果你对线性地址到物理地址是如何映射的感兴趣,请参考另一篇笔记《OS 学习笔记导航》

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值