Linux下shmget对同一key返回不同ID的问题咨询
问题根因
- 核心问题出在服务端创建挂载共享内存后立即执行了
shmctl(pamiec,IPC_RMID,0)标记删除,这是Linux System V共享内存的固有特性导致的:调用
shmctl传入IPC_RMID后,共享内存段的关联key会被立即从系统IPC标识表中移除,不会再响应后续的shmget查询请求。只有当所有绑定该段的进程都执行shmdt解绑后,内存段才会被实际销毁,但此时key已经失效,新进程无法通过原key关联到该段。 - 两种启动顺序的差异逻辑:
- 先启客户端再启服务端:客户端创建共享内存后,没有立刻执行
IPC_RMID(客户端的删除操作放在了传输结束后),key处于有效状态,服务端shmget可以匹配到现有段,因此ID一致,运行正常。 - 先启服务端再启客户端:服务端创建完共享内存立刻打了
IPC_RMID标记,key立即失效,客户端执行shmget时找不到对应key的内存段,就会新建一个同key的新段,因此两端ID不一致,无法正常通信。
- 先启客户端再启服务端:客户端创建共享内存后,没有立刻执行
修复方案
- 核心修改:移除服务端创建挂载共享内存后立即执行的
shmctl(IPC_RMID)调用,将共享内存的删除逻辑延后到传输完全结束后执行。 - 逻辑优化建议:约定好共享内存的删除责任方,比如统一由最后完成操作的一方(即收到EOF确认信号的服务端,在
semafor_p(2)执行完成后)调用shmctl(IPC_RMID),或者由客户端在传输结束后统一删除,避免提前销毁标识。 - 可选健壮性优化:两端调用
shmget时,可先尝试不带IPC_CREAT获取已有段,获取失败再走创建逻辑,避免意外产生冗余共享内存段;程序异常退出时注意清理残留的IPC资源,可通过ipcs、ipcrm命令手动排查清理。
内容的提问来源于stack exchange,提问作者Konrad Stolarz
相关产品推荐
相关产品推荐

