【问题标题】:Why does System V shared memory have separate get and attach functions?为什么 System V 共享内存有单独的 get 和 attach 函数?
【发布时间】:2013-11-19 11:15:40
【问题描述】:

使用 System V 共享内存 IPC 需要调用以下两个函数:

int shmget(key_t key, size_t size, int shmflg);
void *shmat(int shmid, const void *shmaddr, int shmflg);

为什么它们被设计成独立的,而不是有一个接受这些参数的函数,执行这两个函数并简单地返回地址?

我们可以将文件视为类比。字符串(文件路径)上的open 为我们提供了文件描述符,我们使用它来读取/写入文件。完成后,我们在文件描述符上close。这样的设计看起来很自然,我们不用open用字符串得到描述符,然后attach得到描述符。

作为我的想法的一个例子,看看FreeBSD sendmail shared memory implementation

这种分离(shm_openmmap)在POSIX共享内存中也存在,但原因是mmapshm_open实现之前就存在并且可以复用,而mmap需要描述符(来源:UNIX 网络编程第 2 卷,R. Stevens,第 13 章,第 326 页)。

【问题讨论】:

    标签: unix posix ipc shared-memory


    【解决方案1】:

    我能想到的一个可能原因是: (来自manpage of shmget

    • 在 fork(2) 之后,子进程继承了附加的共享内存段。
    • 在 execve(2) 之后,所有附加的共享内存段都与进程分离。
    • 在 _exit(2) 时,所有附加的共享内存段都与进程分离。

    嗯,从技术上讲,附加和分离是在 shmget 期间保留的共享内存段上的基本引用计数。

    分配共享内存段的功能,通过 shmget 和引用计数(向上或向下,分别通过 shmat 和 shmdt)是独立的,因此代码可以在 fork 和 exec 期间重用。

    如果它们都被打包到同一个函数中,那么无论如何您都需要一个单独的函数,它只是进行引用计数(在 fork/exec 期间调用)。所以,我觉得这个设计只是为了促进代码复用,避免代码重复。

    【讨论】:

    • 对于文件,forkexec 处理复制文件描述符和更新内核中的引用计数。文件没有“附加”。为什么shmat 会暴露给用户,而它可以像文件一样在内核中完成?
    【解决方案2】:

    共享内存可能是允许 IPC 的最快方式之一,因为不需要复制数据,但与之相关的问题是同步多个线程之间的访问。您可以使用信号量或记录锁来做到这一点,我们最终在 unix 中使用共享内存中的后者,即使它们不如它们简单高效,系统清理得很好,而且您不需要一些金光闪闪信号量带来。 让我们看看它们是如何工作的,以了解它们为何如此实现。

    进来的是 linux 内核使用的 shmid_ds (http://www.tldp.org/LDP/lpg/node68.html) shm_nattch 是当前附件的无符号整数计数器。 shmget 为您获取 shm id 并设置诸如 ipc_perm、日期、pid、atime ctime、段大小请求 (shm_segsz) 之类的内容 接下来,shmctl 开始使用 IPC_STAT、IPC_RMID、IPC_SET 为 ipc 做一些事情,例如设置 perms、获取或删除段的 shm_id,甚至锁定或解锁它。

    一旦段准备就绪,进程就会使用 shmat 附加到其地址空间,具体取决于标志和地址参数。一旦它附加内核就会增加 shm_nattch。分离时,我们调用 shmdt 来分离。标识符和相关数据结构的删除不是自动的,某些进程必须使用 IPC_RMID 调用 shmctl 并取决于 shm_perm

    如您所见,这与使用信号量的方式非常相似,并且实现很有意义。

    【讨论】:

      猜你喜欢
      • 2011-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-06
      • 1970-01-01
      • 1970-01-01
      • 2011-01-09
      • 2012-10-31
      相关资源
      最近更新 更多