Linux进程间通信 共享内存

发表于:2010-4-06 09:55

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:未知    来源:51Testing软件测试网采编

  Linux为共享内存提供了四种操作。

  1. 共享内存对象的创建或获得。与其它两种IPC机制一样,进程在使用共享内存区域以前,必须通过系统调用sys_ipc (call值为SHMGET)创建一个键值为key的共享内存对象,或获得已经存在的键值为key的某共享内存对象的引用标识符。以后对共享内存对象的访 问都通过该引用标识符进行。对共享内存对象的创建或获得由函数sys_shmget完成,其定义如下:

  int sys_shmget (key_t key, int size, int shmflg)

  这里key是表示该共享内存对象的键值,size是该共享内存区域的大小(以字节为单位),shmflg是标志(对该共享内存对象的特殊要求)。

  它所做的工作如下:

  1) 如果key == IPC_PRIVATE,则创建一个新的共享内存对象。

  * 算出size对应的页数,检查其合法性。
  * 搜索向量表shm_segs,为新创建的共享内存对象找一个空位置。
  * 申请一块内存用于建立shmid_kernel数据结构,注意这里申请的内存区域大小不包括真正的共享内存区,实际上,要等到第一个进程试图访问它的时候 才真正创建共享内存区。
  * 根据该共享内存区所占用的页数,为其申请一块空间用于建立页表(每页4个字节),将页表清0。
  * 填写shmid_kernel数据结构,将其加入到向量表shm_segs中为其找到的空位置。
  * 返回该共享内存对象的引用标识符。

  2) 在向量表shm_segs中查找键值为key的共享内存对象,结果有三:

  * 如果没有找到,而且在操作标志shmflg中没有指明要创建新共享内存,则错误返回,否则创建一个新的共享内存对象。
  * 如果找到了,但该次操作要求必须创建一个键值为key的新对象,那么错误返回。
  * 否则,合法性、认证检查,如有错,则错误返回;否则,返回该内存对象的引用标识符。

  共享内存对象的创建者可以控制对于这块内存的访问权限和它的key是公开还是私有。如果有足够的权限,它也可以把共享内存锁定在物理内存中。

  参见include/linux/shm.h

  2. 粘附。在创建或获得某个共享内存区域的引用标识符后,还必须将共享内存区域映射(粘附)到进程的虚拟地址空间,然后才能使用该共享内存区域。系统调用 sys_ipc(call值为SHMAT)用于共享内存区到进程虚拟地址空间的映射,而真正完成粘附动作的是函数sys_shmat,其定义如下:

  int sys_shmat (int shmid, char *shmaddr, int shmflg, ulong *raddr)

  其中:

  shmid是共享内存对象的引用标识符;
  shmaddr该共享内存区域在进程的虚拟地址空间对应的虚拟地址;
  shmflg是映射标志;
  raddr是实际映射的虚拟空间地址。

  该函数所做的工作如下:

  1) 根据shmid找到共享内存对象。
  2) 如果shmaddr为0,即用户没有指定该共享内存区域在它的虚拟空间中的位置,则由系统在进程的虚拟地址空间中为其找一块区域(从1G开始);否则,就 用shmaddr作为映射的虚拟地址。
  3) 检查虚拟地址的合法性(不能超过进程的最大虚拟空间大小—3G,不能太接近堆栈栈顶)。
  4) 认证检查。
  5) 申请一块内存用于建立数据结构vm_area_struct,填写该结构。
  6) 检查该内存区域,将其加入到进程的mm结构和该共享内存对象的vm_area_struct队列中。

  共享内存的粘附只是创建一个vm_area_struct数据结构,并将其加入到相应的队列中,此时并没有创建真正的共享内存页。

  当进程第一次访问共享虚拟内存的某页时,因为所有的共享内存页还都没有分配,所以会发生一个page fault异常。当Linux处理这个page fault的时候,它找到发生异常的虚拟地址所在的vm_area_struct数据结构。在该数据结构中包含有这类共享虚拟内存的一组处理例程,其中的 nopage操作用来处理虚拟页对应的物理页不存在的情况。对共享内存,该操作是shm_nopage(定义在ipc/shm.c中)。该操作在描述这个 共享内存的shmid_kernel数据结构的页表shm_pages中查找发生page fault异常的虚拟地址所对应的页表条目,看共享页是否存在(页表条目为0,表示共享页是第一次使用)。如果不存在,它就分配一个物理页,并为它创建一 个页表条目。这个条目不但进入当前进程的页表,同时也存到shmid_kernel数据结构的页表shm_pages中。

  当下一个进程试图访问这块内存并得到一个page fault的时候,经过同样的路径,也会走到函数shm_nopage。此时,该函数查看shmid_kernel数据结构的页表shm_pages时, 发现共享页已经存在,它只需把这里的页表项填到进程页表的相应位置即可,而不需要重新创建物理页。所以,是第一个访问共享内存页的进程使得这一页被创建, 而随后访问它的其它进程仅把此页加到它们的虚拟地址空间。

32/3<123>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号