博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
System V 共享内存区
阅读量:6356 次
发布时间:2019-06-23

本文共 4372 字,大约阅读时间需要 14 分钟。

1、概述

  系统调用mmap通过映射一个普通文件实现共享内存。System V 则是通过映射特殊文件系统shm中的文件实现进程间的共享内存通信。也就是说,每个共享内存区域对应特殊文件系统shm中的一个文件。执行过程是先调用shmget,再调用shmat。对于每个共享的内存区,内核维护如下的信息结构,定义在<sys/shm.h>头文件中。

1 struct shmid_ds { 2   struct ipc_perm shm_perm;     /* operation perms */ 3   int shm_segsz;            /* size of segment (bytes) */ 4   time_t shm_atime;          /* last attach time */ 5   time_t shm_dtime;          /* last detach time */ 6   time_t shm_ctime;          /* last change time */ 7   unsigned short shm_cpid;      /* pid of creator */ 8   unsigned short shm_lpid;      /* pid of last operator */ 9   short shm_nattch;          /* no. of current attaches */10   /* the following are private */11   unsigned short shm_npages;      /* size of segment (pages) */12   unsigned long *shm_pages;       /* array of ptrs to frames -> SHMMAX */ 13   struct vm_area_struct *attaches;   /* descriptors for attaches */14 };

参考网址:

2、System V 共享内存区API

  使用共享内存的流程:

   1.进程必须首先分配它。
   2.随后需要访问这个共享内存块的每一个进程都必须将这个共享内存绑定到自己的地址空间中。
   3.当完成通信之后,所有进程都将脱离共享内存,并且由一个进程释放该共享内存块。

#include 
#include
/*创建一个新的内存共享区或者访问一个已经存在的共享内存区返回共享内存区标识符*/int shmget(key_t key, size_t size, int shmflg);/*创建或打开一个共享内存区后,调用shmat把它连接到调用进程的地址空间*/void *shmat(int shmid, const void *shmaddr,int shmflg);/*当一个进程完成某个共享内存区的使用时,调用shmdt断开这个内存区*/int shmdt(const void *shmaddr);/*对内存区进行多种操作cmd取值:IPC_RMID:从系统中删除由shmid标识的共享内存区并拆除它IPC_SET:给指定的共享内存区设置其shmid_ds结果成员IPC_STAT:通过buff参数向调用者返回所指定共享内存区当前的shmid_ds结构*/int shmctl(int shmid, int cmd, struct shmid_ds *buf);

调用System V API编写程序进行测试:

程序1:调用shmget函数使用指定的路径名和长度创建一个共享内存区,程序如下:

1 #include 
2 #include
3 #include
4 #include
5 #include
6 7 #define SVSHM_MODE (SHM_R | SHM_W | SHM_R>>3 | SHM_R>>6) 8 9 int main(int argc,char *argv[])10 {11 int c,id,oflag;12 char *ptr;13 size_t length;14 oflag = SVSHM_MODE | IPC_CREAT;15 while(( c = getopt(argc,argv,"e")) != -1)16 {17 switch(c)18 {19 case 'e':20 oflag |= O_EXCL;21 break;22 }23 }24 if (optind != argc -2)25 {26 printf("usage: shmget [-e]
.\n");27 exit(0);28 }29 length = atoi(argv[optind + 1]);30 //创建由用户指定其名字和大小的共享内存区31 id = shmget(ftok(argv[optind],0),length,oflag);32 //把该内存区连接到当前进程的地址空间33 ptr = shmat(id,NULL,0);34 exit(0);35 }

程序2:调用shmctl指定IPC_RMID命令,从系统中删除一个共享内存区,程序如下:

1 #include 
2 #include
3 #include
4 #include
5 6 #define SVSHM_MODE (SHM_R | SHM_W | SHM_R>>3 | SHM_R>>6) 7 8 int main(int argc,char* argv[]) 9 {10 int id;11 if(argc != 2)12 {13 printf("usage: shmrmid
\n");14 exit(0);15 }16 //打开共享内存区17 id = shmget(ftok(argv[1],0),0,SVSHM_MODE);18 //从系统中删除由id标识的共享内存区19 shmctl(id,IPC_RMID,NULL);20 exit(0);21 }

程序3:往共享内存区中写入一个模式,调用shmctl指定IPC_STAT命令格式,程序如下:

1 #include 
2 #include
3 #include
4 #include
5 #include
6 7 #define SVSHM_MODE (SHM_R | SHM_W | SHM_R>>3 | SHM_R>>6) 8 9 int main(int argc,char *argv[])10 {11 int i,id;12 struct shmid_ds buff;13 unsigned char *ptr;14 if(argc != 2)15 {16 printf("usage: shmwrite
.\n");17 exit(0);18 }19 id = shmget(ftok(argv[1],0),0,SVSHM_MODE);20 ptr = shmat(id,NULL,0);21 shmctl(id,IPC_STAT,&buff); //获取共享内存区大小22 for(i=0;i

程序4:从共享内存去中读出模式,程序如下:

1 #include 
2 #include
3 #include
4 #include
5 #include
6 7 #define SVSHM_MODE (SHM_R | SHM_W | SHM_R>>3 | SHM_R>>6) 8 9 int main(int argc,char *argv[])10 {11 int i,id;12 struct shmid_ds buff;13 unsigned char c,*ptr;14 if(argc != 2)15 {16 printf("usage: shmread
.\n");17 exit(0);18 }19 id = shmget(ftok(argv[1],0),0,SVSHM_MODE);20 ptr = shmat(id,NULL,0);21 shmctl(id,IPC_STAT,&buff);22 for(i=0;i

 3、System V 与Posix 共享内存区

  二者的差别是:

(1)Posix共享内存区是先调用shm_open然后再调用mmap,System V 共享内存区是先调用shmget再调用shmat。

(2)Posix共享内存区对象的大小可在任何时刻通过ftruncate修改,而System V 共享内存区对象的大小是在调用shmget创建时固定下来的。

 

转载地址:http://fszma.baihongyu.com/

你可能感兴趣的文章
redis zset 顺序问题
查看>>
C# 判断网站是不是discuz论坛
查看>>
[转载] 七龙珠第一部——第001话 布玛与孙悟空
查看>>
linux 内核升级
查看>>
BZOJ1791[Ioi2008]Island 岛屿 ——基环森林直径和+单调队列优化DP+树形DP
查看>>
文件共享及dup函数
查看>>
jQurey动态添加/删除DIV(原创自Zjmainstay)
查看>>
Android流量统计TrafficStats类的使用
查看>>
View实现涂鸦、撤销以及重做功能【转】
查看>>
快速构建实时抓取集群
查看>>
Apache Server 负载均衡
查看>>
php+js+mysql设计的仿webQQ-<7>聊天消息的发送与刷新
查看>>
2009年程序员考试大纲指南
查看>>
SQL安全管理范例-创建一个只能在应用程序中登录才有权限的用户.sql
查看>>
[zz] convirt 安装指南
查看>>
HUT-1697 棋盘覆盖
查看>>
ubuntu 12.04 lamp配置
查看>>
atitit。浏览器缓存机制 and 微信浏览器防止缓存的设计 attilax 总结
查看>>
用JAX-WS在Tomcat中公布WebService
查看>>
meclipse中project facet问题
查看>>