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. 错误: 找不到或无法加载主类 Files\red5-server ,原因与解决办法

    因为你把 red5放到了 Program Files 下,而Program Files 中间有个空格,启动路径不允许有空格,换个没空格的路径就OK啦

  2. ajax与java前后台传值及数据表查询解决一个bug的问题

    前台选中某些表,确定提交到后台,偶尔会报500错误,通过排查发现:由于后台代码写的不严谨,导致前台选中的表名如果全不存在的话就会导致后台走异常报500错误,所以决定在前台先对数据进行一次过滤,使至少有 ...

  3. Java基础(九):抽象类

    在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类. 抽象类除了不能实例化对象之外, ...

  4. 理解JavaScript里this关键字

    1.全局代码中的this:始终指向window 2.函数代码中的this: }; var bar = { x: , test: function () { alert(this === bar); a ...

  5. Linq-语句之存储过程

    存储过程 在我们编写程序中,往往需要一些存储过程,在LINQ to SQL中怎么使用呢?也许比原来的更简单些.下面我们以NORTHWND.MDF数据库中自带的几个存储过程来理解一下. 1.标量返回 在 ...

  6. Passing address of non-local object to __autoreleasing parameter for write-back

    在希望通过函数的參数返回Objective-C对象的时候.遇到了这个问题 错误代码例如以下: - (void)methodA:(NSString **)string<span style=&qu ...

  7. HDU 1199 &amp;&amp; ZOJ 2301 线段树离散化

    一段长度未知的线段.一种操作:a b c ,表示区间[a,b]涂为颜色C,w代表白色,b代表黑色,问终于的最长连续白色段,输出起始位置和终止位置 离散化处理.和寻常的离散化不同,须要把点化成线段.左闭 ...

  8. java.lang.NoClassDefFoundError: com.baidu.mapapi.BMapManager

    解决方案:一.右击项目->properties->Java Build Path->Order and Export,在需要引用的包前面打勾.二.Project->Clean. ...

  9. 使用GCD创建单例

    + (KKTextHUB *)sharedTextHUB { static KKTextHUB *sharedHub = nil; static dispatch_once_t onceToken; ...

  10. TP3.2 APP_DEBUG=false关闭调试后访问不了。页面错误!请稍后再试~

    在APP_DEBUG=true时是没问题的,在APP_DEBUG=false时才会出现找不到模板的问题.  经过排查可能是模板文件找不到问题,之前是这么写的. 改为这个就好了. ----------- ...