为什么System V共享内存具有单独的get和attach功能?

时间:2013-11-07 17:10:18

标签: unix posix ipc shared-memory

使用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共享内存中,但原因是在mmap实施之前shm_open存在并且可以重复使用,mmap需要描述符(来源:UNIX Network Programming Vol.2,R。Stevens,第13章,第326页)。

2 个答案:

答案 0 :(得分:0)

共享内存可能是允许IPC的最快方法之一,因为无需复制数据,但与之相关的问题是同步多个线程之间的访问。您可以使用信号量或记录锁执行此操作,我们最终使用unix中的更高版本来共享内存,即使它们不是那么简单,系统清理得很好,而且您不需要一些bling信号量带来。 让我们看看这些如何工作以理解为什么它们被实现。

来自linux内核使用的shmid_ds(http://www.tldp.org/LDP/lpg/node68.html) shm_nattch是当前附加的unsigned int计数器。 shmget获取一个shm id并设置类似ipc_perm,日期,pid,atime ctime,段大小的请求(shm_segsz) 接下来,shmctl启动并使用IPC_STAT,IPC_RMID,IPC_SET设置perms,获取或删除段的shm_id,甚至锁定或解锁它来为ipc做东西。

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

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

答案 1 :(得分:0)

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

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

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

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

如果它们都被打包到同一个函数中,你总是需要一个单独的函数,它只是引用计数(在fork / exec期间调用)。所以,我认为这个设计只是为了促进代码重用,并避免代码重复。