访问由 IPC_PRIVATE 生成的 key_t

Accessing key_t generated by IPC_PRIVATE

我正在尝试同步并使一些 threads/processes 为项目进行通信,理想情况下我希望访问它们之间的一些共享内存块,而不会让它们与其他 processes/resources 发生冲突.

我知道 IPC_PRIVATE 会在调用 shmget() 创建它时生成一个唯一的密钥,但是如果我随后需要该密钥在其他进程中的某处打开该区域,我该如何访问生成的那个key_t 值以便我可以将它发送到其他进程?

我目前正在通过 IPC 消息队列发送数据,因此我可以发送 shmid 值,但据我所知这是行不通的,因为 shmid 值对于每个进程都是唯一的。

除了 ftok() 和一些随机文件,我别无选择吗?我是否必须为每个要创建的不同共享内存块选择不同的文件?

感谢您的宝贵时间。

I know IPC_PRIVATE will generate a unique key when calling shmget() to create it

不对,你误会了。 IPC_PRIVATE 不会 生成 一个 key_t,它 一个 key_t。这个特殊的 key_t 引出了 shmget() 的特殊行为,即始终创建一个新段,忽略除模式位之外的所有标志位。

if I then need that key to open that region somewhere in other processes, how can I access that generated key_t value so that I can send it to the other process?

由于您总是通过 IPC_PRIVATE 获得一个新段,因此您无法在进程之间共享内存,每个进程都通过该键独立获取共享内存段。相反,对于通过这样的段进行通信的两个或多个进程,(插入 2021-12-19)它们可能会交换其中一个从 shmget() 获得的 shmid他们必须可能都从创建它的共同祖先进程(或创建它的进程)继承了它。相互之间没有这种关系的进程不能使用IPC_PRIVATE键访问同一个段。

Do I have no other options but try luck with ftok() and some random files? Do I have to choose a different file for each block of different shared memory I wish to create?

由于您使用的是 System-V 共享内存,因此您可以选择使用 ftok() 根据现有路径生成密钥,但不必是 任意文件。您可以使用具有特定协作进程组特征的文件的路径——输入文件、工作目录或类似文件。此外,ftok() 还使用一个整数“项目 ID”,您可以使用它来区分不相关的运行,或用于不同目的或类似用途的多个不同键。如果你没有其他好的区分方法,你可以在那里选择一些指定进程的进程号。

请注意,顺便说一下,System-V IPC 接口非常笨重。它们确实有一些与众不同的特性,有时可能会使它们更受欢迎,但较新的 POSIX 接口(shm_open() 等)通常是更好的选择。但是,POSIX 版本并未针对您提出的问题提供特别好的解决方案。

我认为上面的答案不正确。

首先,ipcrm 程序可以选择通过 id 而不是按键删除共享对象:

 -m, --shmem-id shmid
           Remove the shared memory segment identified by shmid after
           the last detach is performed. in case of shared memory.

这个事实告诉我们 id 是全局的。

其次,我刚刚编写了一个创建消息队列的程序 IPC_PRIVATE 并且服务器进程(与客户端无关)能够响应 合并到传入消息中的消息 ID。

我记得大约 20 年前对共享内存做过同样的事情。