当我有几个进程正在使用共享内存时,我将它们全部分开。
shmctl()
(使用该进程)删除共享内存之前,拆除最后一个进程是否合理? 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
没有附加到任何进程,它将立即被销毁。