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. Bootstrap学习js插件篇之提示框

    案例 受到Jason Frame开发的jQuery.tipsy插件的启发,我们才把这个工具提示插件做的更好,而且此插件不依赖图片,只是使用CSS3来实现动画效果,并使用data属性存储标题. 将鼠标悬 ...

  2. java编程思想---对象

    一.对象 对于每种语言来说,都有自己操纵内存中元素的方法. 在java中,一切被视为对象.可是操纵对象的是一个"引用".举个样例,能够比作为遥控器对电视的操作,遥控器就是引用,而电 ...

  3. nyoj-659-推断三角形(大坑)

    推断三角形 时间限制:1000 ms  |  内存限制:65535 KB 难度: 描写叙述 小明非常喜欢研究三角形.如今,小明已经知道三角形的三条边.假设三条边能组成三角形,小明就会非常高兴,他就会得 ...

  4. Smack 结合 Openfire服务器,建立IM通信,发送聊天消息

    在文章开始,请你了解和熟悉openfire方面的相关知识,这样对你理解下面代码以及下面代码的用途有很好的了解.同时,你可能需要安装一个简单的CS聊天工具,来测试你的代码是否成功的在openfire服务 ...

  5. 'htmlentities(): charset `utf8' not supported, assuming utf-8'

    TP5.1框架报错!  Fatal error: Uncaught exception 'think\exception\ErrorException' with message 'htmlentit ...

  6. WQL语言简介和WQL测试工具wbemtest.exe使用方法详细介绍

    这篇文章主要介绍了WQL语言简介和WQL测试工具wbemtest.exe使用方法详细介绍,WQL是指Windows管理规范查询语言,需要的朋友可以参考下 WQL就是WMI中的查询语言,WQL的全称是W ...

  7. Windows删除无效服务

    W+R运行:regedit http://os.51cto.com/art/201208/354989.htm

  8. vue 源码 断点调试

    1.添加sourceMap sourceMap: true 2.npm run dev 会生成vue.js.map 3.断点调试 <!DOCTYPE html> <html> ...

  9. 升级openssh基于openssl

    OpenSSH is the premier connectivity tool for remote login with the SSH protocol. It encrypts all tra ...

  10. hdu 4857 逃生 (拓扑排序+保证最小在前面)

    逃生 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submiss ...