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

当我有几个进程正在使用共享内存时,我将它们全部分开。

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

shmctl()的手工输入没有shmctl() “最多使用一个进程”或“没有进程使用它”。 但是,系统不能完全破坏已经连接到共享内存段的正在运行的进程。

你只需要shmget()返回的shmid (共享内存段ID shmget() ; 你不需要连接共享内存(所以你可能已经运行了shmdt() )。

在Mac上测试(macOS Sierra 10.12.3,GCC 6.3.0),代码来源于前面的问题( 在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,进程不受影响,且在完成两者之后该段已被删除。

shmctl(,... IPC_RMID, ...)的行为没有被SingleUnix明确定义:

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

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

在Linux上,销毁是懒惰的,只有在最后一个进程分离时才会销毁该分段:

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

FreeBSD上也有相同的行为:

在所有连接分段的进程退出之前,移除将不会生效。

Solaris具有类似的功能 ,但向后解释:

如果在调用IPC_RMID没有附加到任何进程,它将立即被销毁。