在删除之前从共享内存中分离

时间:2017-02-15 19:33:43

标签: c linux sysv-ipc

当我使用共享内存进行多个进程时,我将所有进程分开但只有一个。

  1. 在使用shmctl()(使用该进程)删除共享内存之前分离最后一个进程是否有意义?
  2. 如果它没有意义,是否可能在从中删除后删除共享内存?

2 个答案:

答案 0 :(得分:2)

shmctl()的手动输入并未说明“最多使用它的一个进程”或“没有附加进程”。但是,系统无法完全中断已连接到共享内存段的已运行进程。

您只需要shmget()返回的shmid(共享内存段ID);您不需要附加共享内存(因此您可能已经运行shmdt())。

在Mac上进行测试(macOS Sierra 10.12.3,GCC 6.3.0),其代码来自前一个问题(Making a shared data structure in C),我添加了一个选项-t time以使进程为可指定的期限。然后我创建了一个共享内存段并让进程保持打开状态。我使用ipcs -m来查看该细分受众群是否存在。然后我删除了段;它很成功。重新检查ipcs -m,该细分已从共享更改为IPC_PRIVATE。当休眠过程完成时,共享内存段被自动删除(因为私有段始终是)。

$  shm-master -f shm-master -s 1024 -x -t 120 &
[1] 14392
$ ID: 0, File: shm-master
Key: 0x00041BF7
ShmID: 1441795
Shared memory allocated at 0x10F2B4000
Sleeping for 120 seconds

$ ipcs -m
IPC status from <running system> as of Wed Feb 15 11:56:37 PST 2017
T     ID     KEY        MODE       OWNER    GROUP
Shared Memory:
m  65536 0x00fedc64 --rw-rw-rw-     root    wheel
m  65537 0x0052e2c1 --rw------- postgres   daemon
m  65538 0x52042973 --rw-------     root    wheel
m 1441795 0x00041bf7 --rw------- jleffler    staff

$ shm-master -f shm-master -s 1024 -d
ID: 0, File: shm-master
Key: 0x00041BF7
ShmID: 1441795
Shared memory removed
$ ipcs -m
IPC status from <running system> as of Wed Feb 15 11:56:47 PST 2017
T     ID     KEY        MODE       OWNER    GROUP
Shared Memory:
m  65536 0x00fedc64 --rw-rw-rw-     root    wheel
m  65537 0x0052e2c1 --rw------- postgres   daemon
m  65538 0x52042973 --rw-------     root    wheel
m 1441795 0x00000000 --rw------- jleffler    staff

$ sleep 120; ipcs -m
Detached from shared memory
[1]+  Done                    shm-master -f shm-master -s 1024 -x -t 120
IPC status from <running system> as of Wed Feb 15 11:58:57 PST 2017
T     ID     KEY        MODE       OWNER    GROUP
Shared Memory:
m  65536 0x00fedc64 --rw-rw-rw-     root    wheel
m  65537 0x0052e2c1 --rw------- postgres   daemon
m  65538 0x52042973 --rw-------     root    wheel

$

这是否是其他系统上发生的事情,我不确定,但看起来似乎是合理的行为。可能会出现类似情况。

顺便说一句,运行一个进程来创建段,第二个只是连接到它,两个都在睡眠模式下运行,并没有真正改变观察到的结果。共享内存段密钥更改为0,进程不受影响,并且在完成两个段后删除了该段。

答案 1 :(得分:1)

SingleUnix未明确定义shmctl(,... IPC_RMID, ...)的行为:

  

从系统中删除shmid指定的共享内存标识符,并销毁与之关联的共享内存段和shmid_ds数据结构。

有人可能会说,IPC_RMID应该立即使对共享内存段的所有引用无效。在实践中,移除被延迟直到大多数实现最后一个过程分离,这更符合人们期望的典型语义。来自FIFO。该名称被删除,但真正的内核对象只有在释放所有引用后才会消失。

在Linux上,破坏是懒惰的,只有在last process detaches

后,该段才会被销毁
  

该段仅在最后一个进程分离后才被实际销毁(即,当关联结构shmid_ds的shm_nattch成员为零时)。

FreeBSD上存在相同的行为:

  

在所有已附加该段的进程退出后,删除才会生效。

Solaris有它similarly,但向后解释:

  

如果在调用IPC_RMID时段未附加到任何进程,则会立即将其销毁。