在删除之前从共享内存中分离
Detaching from shared memory before removing it
当我有多个进程在使用共享内存时,我将所有进程分离,只留下一个。
- 在使用
shmctl()
删除共享内存之前分离最后一个进程是否有意义(与那个进程)?
- 如果没有意义,是否可以在分离后删除共享内存?
shmctl(,... IPC_RMID, ...)
的行为未由 SingleUnix 明确定义:
Remove the shared memory identifier specified by shmid
from the system and destroy the shared memory segment and shmid_ds
data structure associated with it.
有人可能会争辩说,IPC_RMID
应该立即使所有对共享内存段的引用无效。在实践中,删除被延迟到大多数实现的最后一个进程分离,这更符合人们期望的典型语义,例如从一个先进先出。名称被删除,但真正的内核对象只有在所有引用都被释放后才会消失。
在 Linux 上,销毁是惰性的,该段只会在 last process detaches:
时被销毁
The segment will only actually be destroyed after the last process detaches it (i.e., when the shm_nattch member of the associated structure shmid_ds is zero).
FreeBSD 上存在相同的行为:
The removal will not take effect until all processes having attached the segment have exited.
Solaris 有它 similarly,但向后解释:
If the segment is not attached to any process when IPC_RMID
is invoked, it will be destroyed immediately.
shmctl()
的手动输入没有说明 'at most one process using it' 或 'no processes attached to it'。但是,系统无法完全中断已附加到共享内存段的 运行 个进程。
你只需要shmget()
; you don't need the shared memory to be attached (so you could already have run shmdt()
返回的shmid
(共享内存段ID)。
使用源自上一个问题 () 的代码在 Mac(macOS Sierra 10.12.3、GCC 6.3.0)上进行测试,我添加了一个选项 -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()
删除共享内存之前分离最后一个进程是否有意义(与那个进程)? - 如果没有意义,是否可以在分离后删除共享内存?
shmctl(,... IPC_RMID, ...)
的行为未由 SingleUnix 明确定义:
Remove the shared memory identifier specified by
shmid
from the system and destroy the shared memory segment andshmid_ds
data structure associated with it.
有人可能会争辩说,IPC_RMID
应该立即使所有对共享内存段的引用无效。在实践中,删除被延迟到大多数实现的最后一个进程分离,这更符合人们期望的典型语义,例如从一个先进先出。名称被删除,但真正的内核对象只有在所有引用都被释放后才会消失。
在 Linux 上,销毁是惰性的,该段只会在 last process detaches:
时被销毁The segment will only actually be destroyed after the last process detaches it (i.e., when the shm_nattch member of the associated structure shmid_ds is zero).
FreeBSD 上存在相同的行为:
The removal will not take effect until all processes having attached the segment have exited.
Solaris 有它 similarly,但向后解释:
If the segment is not attached to any process when
IPC_RMID
is invoked, it will be destroyed immediately.
shmctl()
的手动输入没有说明 'at most one process using it' 或 'no processes attached to it'。但是,系统无法完全中断已附加到共享内存段的 运行 个进程。
你只需要shmget()
; you don't need the shared memory to be attached (so you could already have run shmdt()
返回的shmid
(共享内存段ID)。
使用源自上一个问题 (-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,进程不受影响,段都完成后被删除。