科技报道|- 共享内存,多进程编程( 二 )


SHM_RDONLY:进程仅能读取共享内存中的内容 。 若没有指定该标志 , 则进程可同时对共享内存进行读写操作(当然 , 这需要在创建共享内存的时候指定其读写权限)SHM_REMAP:如果地址shmaddr已经被关联到一段共享内存上 , 则重新关联SHM_EXEC:它指定对共享内存段的执行权限 。 对共享内存而言 , 执行权限实际上和读权限是一样的 。shmat成功时返回共享内存被关联到的地址 , 失败则返回(void*)-1并设置errno 。 shmat成功时 , 将修改内核数据结构shmid_ds的部分字段:
将shm_nattach加1将shm_lpid设置为调用进程PID将shm_atime设置为当前的时间shmdt函数将关联到的shm_addr处的共享内存从进程中分离 。 它成功时返回0 , 失败则返回-1并设置errno 。 shmdt在成功调用时将修改内核数据结构shmid_ds的部分字段:
将shm_nattach减1将shm_lpid设置为调用进程的PID将shm_dtime设置为当前的时间shmctl系统调用shmctl系统调用控制共享内存的某些属性 。 定义如下:
#includeintshmctl(intshm_id,intcommand,structshmid_ds*buf);其中 , shm_id参数是由shmget调用返回的共享内存标识符 。 command参数指定要执行的命令 。 shm_ctl支持的所有命令如下表:
共享内存的POSIX方法mmap函数利用它的MAP_ANONYMOUS标志可以实现父、子进程之间的匿名内存共享 。 通过打开同一个文件按 , mmap可以实现无关进程之间的内存共享 。 Linux提供了另外一种利用mmap在无关进程之间共享内存的方式 。 这种方式无需任何文件的支持 , 但它需要先使用如下函数创建或打开一个POSIX可移植操作系统接口(PortableOperatingSystemInterfaceofUNIX , 缩写为POSIX)共享内存对象:
#include#include#includeintshm_open(constchar*name,intoflag,mode_tmode);shm_open的使用方法与open系统调用完全相同 。
name参数指定要创建/打开的内存 。 从可移植性的角度考虑 , 该参数应该使用“/somename”的格式:
以“/”开始 , 后接多个字符 , 且这些字符都不是“/”;
以“0"结尾 , 长度不超过NAME_MAX(通常是255)
oflag参数指定创建方式 。 它可以是下列标志中的一个或者多个按位或:
O_RDONLY:以只读方式打开共享内存对象O_RDWR:以可读、可写方式打开内存共享对象O_CREAT:如果共享内存对象不存在 , 则创建之 。 此时mode参数的最低9位将指定该共享内存对象的访问权限 。 共享内存对象被创建的时候 , 其初始长度为0 。 O_EXCL:和O_CREAT一起使用 , 如果由name指定的共享内存已经存在 , 则shm_open调用返回错误 , 否则就创建一个新的共享内存对象O_TRUNC:如果共享内存已经存在 , 则把它截断 , 使其长度为0shm_open调用成功时返回一个文件描述符 。 该文件描述符可用于后续的mmap调用 , 从而将共享内存关联到调用进程 。 shm_open失败时返回-1 , 并设置errno 。
和打开的文件最后需要关闭一样 , 由shm_open创建的共享内存对象使用完之后也需要被删除 。 这个通过如下函数实现:
#include#include#includeintshm_unlink(constchar*name);该函数将name参数指定的共享内存对象标记为等待删除 。 当所有使用该共享内存对象的进程都使用ummap将它从进程中分离之后 , 系统将销毁这个共享内存对象所占据的资源 。
如果代码中使用了上述POSIX共享内存函数 , 则编译的时候需要指定链接选项-ltr 。
共享内存实例【科技报道|- 共享内存,多进程编程】在I/O复用高级应用中我们介绍过过一个聊天室程序 。 下面我们将它修改为一个多进程服务器:一个子进程处理一个客户连接 。 同时 , 我们将所有客户socket连接的读缓冲设计为一块共享内存:


推荐阅读