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 };

参考网址: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:


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

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.当完成通信之后,所有进程都将脱离共享内存,并且由一个进程释放该共享内存块。

#include <sys/ipc.h>
#include <sys/shm.h>
/*
创建一个新的内存共享区或者访问一个已经存在的共享内存区
返回共享内存区标识符
*/
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 <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <sys/shm.h>
5 #include <fcntl.h>
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] <pathname> <length>.\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 <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <sys/shm.h>
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 <pathname>\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 <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <sys/shm.h>
5 #include <fcntl.h>
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 <pathname>.\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<buff.shm_segsz;i++)
23 *ptr++ = i % 256;
24 exit(0);
25 }

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

 1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <unistd.h>
4 #include <sys/shm.h>
5 #include <fcntl.h>
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 <pathname>.\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<buff.shm_segsz;i++)
23 {
24 c = *ptr++;
25 printf("ptr[%d] = %d\n",i,c);
26 }
27 exit(0);
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. 检测 USB 设备拨插的 C# 类库:USBClassLibrary

    这是采用C#开发的一个USB库,使您可以管理USB设备的连接和分离事件,探测自己的设备.可以运行在Windows XP和Windows7 64位系统下. 01 private void USBPort ...

  2. maven nexus linux私服搭建

    搭建maven 下载jar包,将apache-maven-3.2.2-bin.tar.gz上传到server 1.解压 tar -zvxf apache-maven-3.2.2-bin.tar.gz ...

  3. (转)Unity3D新手引导开发手记

    转自:http://www.cnblogs.com/ybgame/p/3844315.html 最近开始接手新手引导的开发,记录下这块相关的心得 首先客户端是Unity,在接手前,前面的同学已经初步完 ...

  4. [Webpack] Externalize Dependencies to be Loaded via CDN with webpack

    We can separate our custom application code from the common libraries we leverage, such as React and ...

  5. 5. How to set up a Activity

    1. Create a new xml in "layout" folder "splah.xml" <?xml version="1.0&qu ...

  6. 翻译记忆软件-塔多思TRADO经典教程_2

    Trados 中文简明教程Trados 中文简明教程1. 准备工作 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ...

  7. 解决Synergy的鼠标无法从服务器(server)机屏幕移动到客户机(client)屏幕的问题

    我在工作时使用一台Win 7笔记本和一台Ubuntu台式机,为了提升工作效率,我使用Synergy在两台机器间共享了笔记本的鼠标和键盘,即笔记本作为服务器,台式机作为客户机. 这样使用了大概一年多,但 ...

  8. 【JavaScript】实现复选框的全选、全部不选、反选

    以较为简洁的程序实现复选框的全选.全部不选.反选 操作. 并且将可变的部分设置为JS的参数,以实现代码复用. 全选和全不选 第一个参数为复选框名称,第二个参数为是全选还是全部不选. function ...

  9. 算法笔记_186:历届试题 高僧斗法(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 古时丧葬活动中经常请高僧做法事.仪式结束后,有时会有“高僧斗法”的趣味节目,以舒缓压抑的气氛. 节目大略步骤为:先用粮食(一般是稻米)在地 ...

  10. ci高级使用方法篇之连接多个数据库

    在我们的项目中有时可能须要连接不止一个数据库.在ci中怎样实现呢? 我们在本地新建了两个数据库,例如以下截图所看到的: 改动配置文件database.php文件为例如以下格式(读者依据自己数据库的情况 ...