3

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

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

2 回答 2

2

的手动条目shmctl()没有说明“最多一个进程使用它”或“没有附加到它的进程”。但是,系统不能完全中断已连接到共享内存段的正在运行的进程。

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

在 Mac (macOS Sierra 10.12.3, GCC 6.3.0) 上使用源自上一个问题 ( Making a shared data structure in C ) 的代码在 Mac (macOS Sierra 10.12.3, GCC 6.3.0) 上进行测试,我添加了一个选项-t time以使进程休眠一段可指定的时间。然后我创建了一个共享内存段并让进程保持打开状态。我曾经ipcs -m看到该细分市场存在。然后我删除了该段;它是成功的。重新检查ipcs -m,该段已从 shared 更改为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,进程不受影响,并且在两者都完成后删除该段。

于 2017-02-15T20:00:44.820 回答
1

SingleUnixshmctl(,... IPC_RMID, ...)没有明确定义的行为:

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

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

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

该段只有在最后一个进程将其分离后才会真正被销毁(即,当相关结构 shmid_ds 的 shm_nattch 成员为零时)。

FreeBSD上存在相同的行为:

直到所有附加了该段的进程都退出后,删除才会生效。

Solaris 也有类似的,但向后解释:

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

于 2017-02-15T19:54:01.467 回答