1、概述

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

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

参考网址:http://www.tldp.org/LDP/lpg/node68.html

As with message queues and semaphore sets, the kernel maintains a special internal data structure for each shared memory segment which exists within its addressing space. This structure is of type shmid_ds, and is defined in linux/shm.h as follows:


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

Operations on this structure are performed by a special system call, and should not be tinkered with directly. Here are descriptions of the more pertinent fields:

shm_perm

This is an instance of the ipc_perm structure, which is defined for us in linux/ipc.h. This holds the permission information for the segment, including the access permissions, and information about the creator of the segment (uid, etc).

shm_segsz

Size of the segment (measured in bytes).

shm_atime

Time the last process attached the segment.

shm_dtime

Time the last process detached the segment.

shm_ctime

Time of the last change to this structure (mode change, etc).

shm_cpid

The PID of the creating process.

shm_lpid

The PID of the last process to operate on the segment.

shm_nattch

Number of processes currently attached to the segment.

2、System V 共享内存区API

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

  1. #include <sys/ipc.h>
  2. #include <sys/shm.h>
  3. /*
  4. 创建一个新的内存共享区或者访问一个已经存在的共享内存区
  5. 返回共享内存区标识符
  6. */
  7. int shmget(key_t key, size_t size, int shmflg);
  8. /*
  9. 创建或打开一个共享内存区后,调用shmat把它连接到调用进程的地址空间
  10. */
  11. void *shmat(int shmid, const void *shmaddr,int shmflg);
  12. /*
  13. 当一个进程完成某个共享内存区的使用时,调用shmdt断开这个内存区
  14. */
  15. int shmdt(const void *shmaddr);
  16. /*
  17. 对内存区进行多种操作
  18. cmd取值:
  19. IPC_RMID:从系统中删除由shmid标识的共享内存区并拆除它
  20. IPC_SET:给指定的共享内存区设置其shmid_ds结果成员
  21. IPC_STAT:通过buff参数向调用者返回所指定共享内存区当前的shmid_ds结构
  22. */
  23. int shmctl(int shmid, int cmd, struct shmid_ds *buf);

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

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

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

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

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

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

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

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

  1. 1 #include <stdio.h>
  2. 2 #include <stdlib.h>
  3. 3 #include <unistd.h>
  4. 4 #include <sys/shm.h>
  5. 5 #include <fcntl.h>
  6. 6
  7. 7 #define SVSHM_MODE (SHM_R | SHM_W | SHM_R>>3 | SHM_R>>6)
  8. 8
  9. 9 int main(int argc,char *argv[])
  10. 10 {
  11. 11 int i,id;
  12. 12 struct shmid_ds buff;
  13. 13 unsigned char c,*ptr;
  14. 14 if(argc != 2)
  15. 15 {
  16. 16 printf("usage: shmread <pathname>.\n");
  17. 17 exit(0);
  18. 18 }
  19. 19 id = shmget(ftok(argv[1],0),0,SVSHM_MODE);
  20. 20 ptr = shmat(id,NULL,0);
  21. 21 shmctl(id,IPC_STAT,&buff);
  22. 22 for(i=0;i<buff.shm_segsz;i++)
  23. 23 {
  24. 24 c = *ptr++;
  25. 25 printf("ptr[%d] = %d\n",i,c);
  26. 26 }
  27. 27 exit(0);
  28. 28 }

3、System V 与Posix 共享内存区

  二者的差别是:

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

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

System V 共享内存区的更多相关文章

  1. UNIX环境高级编程——System V 共享内存区

    共享内存区域是被多个进程共享的一部分物理内存.如果多个进程都把该内存区域映射到自己的虚拟地址空间,则这些进程就都可以直接访问该共享内存区域,从而可以通过该区域进行通信.共享内存是进程间共享数据的一种最 ...

  2. System V共享内存区

    要点 shell查看命令:ipcs -m 主要函数 #include <sys/shm.h> //oflag=IPC_CREAT|IPC_EXCL|0644组合 //创建一个内存共享区 i ...

  3. Linux进程通信之System V共享内存

    前面已经介绍过了POSIX共享内存区,System V共享内存区在概念上类似POSIX共享内存区,POSIX共享内存区的使用是调用shm_open创建共享内存区后调用mmap进行内存区的映射,而Sys ...

  4. 阐述linux IPC(五岁以下儿童):system V共享内存

    [版权声明:尊重原创.转载请保留源:blog.csdn.net/shallnet 要么 .../gentleliu,文章学习交流,不用于商业用途]         system V共享内存和posix ...

  5. System V共享内存介绍

    (一)简单概念 共享内存作为一种进程间通信的方式,其相较于其他进程间通信方式而言最大的优点就是数据传输速率快.其内部实现的方式采用了Linux进程地址空间中的mmap文件映射区,将文件内容直接映射到各 ...

  6. 共享内存之——system V共享内存

    System V 的IPC对象有共享内存.消息队列.信号灯(量). 注意:在IPC的通信模式下,不管是共享内存.消息队列还是信号灯,每个IPC的对象都有唯一的名字,称为"键(key)&quo ...

  7. System V共享内存

    目录 1. 概述 2. System V共享内存API shmget shmat shmdt shmctl 3. 简单的程序 代码实现 common.h shmcreate.c shmrmid.c s ...

  8. Linux IPC实践(9) --System V共享内存

    共享内存API #include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, size_t size, int ...

  9. php进程(线程)通信基础--System V共享内存

    PHP默认情况没有开启功能,要支持该功能在编译PHP的时候要加入下面几个选项  System V消息,--enable-sysvmsg   System V信号量支持,--enable-sysvsem ...

随机推荐

  1. [转贴]SSL工作原理

    SSL协议使用不对称加密技术实现会话双方之间信息的安全传递.可以实现信息传递的保密性.完整性,并且会话双方能鉴别对方身份.不同于常用的http协议,我们在与网站建立SSL安全连接时使用https协议, ...

  2. Log 日志工具类 保存到文件 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  3. 超级简单的jquery操作表格(添加/删除行、添加/删除列)

    利用jquery给指定的table添加一行.删除一行 <script language="javascript" src="./jquery.js"> ...

  4. Spark Streaming updateStateByKey案例实战和内幕源码解密

    本节课程主要分二个部分: 一.Spark Streaming updateStateByKey案例实战二.Spark Streaming updateStateByKey源码解密 第一部分: upda ...

  5. SQL Server-已更新或删除的行值要么不能使该行成为唯一行,要么改变了多个行

    在更新没有设置主键的表的时候出现下图中的问题: 问题原因: 这种问题大多是由于没有主键(PK)导致同一张表中存在若干条相同的数据 DBMS存储时,只为其存储一条数据,因为DBMS底层做了优化,以减少数 ...

  6. Ngxtop-Nginx日志实时分析利器

    ngxtop实时解析nginx访问日志,并且将处理结果输出到终端,功能类似于系统命令top,所以这个软件起名ngxtop.有了ngxtop,你可以实时了解到当前nginx的访问状况,再也不需要tail ...

  7. Linux清理磁盘空间

    1.首先确定是否是磁盘满了 命令:   df -h 参数说明: -a:列出所有的文件系统,包括系统特有的/proc等文件系统 -k:以KB的容量显示各文件系统 -m:以MB的容量显示各文件系统 -h: ...

  8. Discuz常见小问题-无法登陆UCenter怎么办

    打开uc_server/model/admin.php找到第22行的$this->cookie_status = 0;改成$this->cookie_status = isset($_CO ...

  9. C语言高速入门系列(二)

    C语言高速入门系列(二) -----转载请注明出处coder-pig 本节引言: 在前面一节中我们对C语言进行了初步的了解,学会了使用IDE进行代码的编写,编译执行! 在这一节中我们会对C语言的基本的 ...

  10. 虎嗅: 小米盒子vs乐视盒子

    机顶盒并非新鲜概念,可一旦和互联网发生了跨界关系,就会产生奇妙的反应.自年初小米盒子和乐视盒子分别在突破重重阻碍成功发售之后,互联网企业进军硬件制造领域的趋势愈发明显.今天我们拿到了两家的盒子产品,从 ...