System V 共享内存区
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 共享内存区的更多相关文章
- UNIX环境高级编程——System V 共享内存区
共享内存区域是被多个进程共享的一部分物理内存.如果多个进程都把该内存区域映射到自己的虚拟地址空间,则这些进程就都可以直接访问该共享内存区域,从而可以通过该区域进行通信.共享内存是进程间共享数据的一种最 ...
- System V共享内存区
要点 shell查看命令:ipcs -m 主要函数 #include <sys/shm.h> //oflag=IPC_CREAT|IPC_EXCL|0644组合 //创建一个内存共享区 i ...
- Linux进程通信之System V共享内存
前面已经介绍过了POSIX共享内存区,System V共享内存区在概念上类似POSIX共享内存区,POSIX共享内存区的使用是调用shm_open创建共享内存区后调用mmap进行内存区的映射,而Sys ...
- 阐述linux IPC(五岁以下儿童):system V共享内存
[版权声明:尊重原创.转载请保留源:blog.csdn.net/shallnet 要么 .../gentleliu,文章学习交流,不用于商业用途] system V共享内存和posix ...
- System V共享内存介绍
(一)简单概念 共享内存作为一种进程间通信的方式,其相较于其他进程间通信方式而言最大的优点就是数据传输速率快.其内部实现的方式采用了Linux进程地址空间中的mmap文件映射区,将文件内容直接映射到各 ...
- 共享内存之——system V共享内存
System V 的IPC对象有共享内存.消息队列.信号灯(量). 注意:在IPC的通信模式下,不管是共享内存.消息队列还是信号灯,每个IPC的对象都有唯一的名字,称为"键(key)&quo ...
- System V共享内存
目录 1. 概述 2. System V共享内存API shmget shmat shmdt shmctl 3. 简单的程序 代码实现 common.h shmcreate.c shmrmid.c s ...
- Linux IPC实践(9) --System V共享内存
共享内存API #include <sys/ipc.h> #include <sys/shm.h> int shmget(key_t key, size_t size, int ...
- php进程(线程)通信基础--System V共享内存
PHP默认情况没有开启功能,要支持该功能在编译PHP的时候要加入下面几个选项 System V消息,--enable-sysvmsg System V信号量支持,--enable-sysvsem ...
随机推荐
- Windows环境搭建Red5流媒体服务器
Windows环境搭建Red5流媒体服务器指南 测试环境:Windows 7 一. 下载安装程序 red5-server 下载地址 https://github.com/Red5/red5-ser ...
- IE6的3像素神奇bug:缘起与解决方案
在我们这样一个神奇的国度,到了2014年了,居然还是有很多人的电脑上用着XP,安装的是IE6,他们没有想过要升级,我们就得想着兼容他们.... 一. 6爷我喝高了,最后一行有重影.那什么是IE6 的3 ...
- Java基础(十五):Java 中的内部类
问:什么是内部类呢? 答:内部类( Inner Class )就是定义在另外一个类里面的类.与之对应,包含内部类的类被称为外部类. 问:那为什么要将一个类定义在另一个类里面呢?清清爽爽的独立的一个类多 ...
- 如何使用Octave 在Ubuntu上科学处理音频
Octave 是一个类似于 Linux 上的 Matlab 的软件,它拥有数量众多的函数和命令,支持声音采集.记录.回放以及音频信号的数字化处理,用于娱乐应用.研究.医学以及其它科学领域.在本教程中, ...
- Error Lookup工具
GetLastError()获取到的错误代码,可以通过VS2013自带的Error Lookup工具来查询错误的描述.
- Java 吸血鬼数字
非常羞愧(事实上没什么羞愧.水平就这样).搞了半晌才写出来了一个Java 版求四位吸血鬼数字的方法 吸血鬼数字是指位数为偶数的数字.能够由一对数字相乘而得到.而这对数字各包括乘积的一半位数的数字,当中 ...
- PG里如何查看表,索引,表空间,数据库大小
--查询一个索引大小 select pg_size_pretty(pg_relation_size('indexname)) --查看一张表及此它上的索引总大小select pg_size_prett ...
- 使用FlashPaper 实现JSP在线阅读[转]
http://cuisuqiang.iteye.com/blog/1841452 使用FlashPaper 实现JSP在线阅读 FlashPaper 是Macromedia推出的一款电子文档类工具,通 ...
- 如何在hosts文件添加自己想要解析的网站?及修改hosts的作用
http://union.zhuna.cn/help/144.asp 在Windows2003/XP系统中位于C:\Winnt\System32\Drivers\Etc 目录中,找到host文件. 首 ...
- 使用javacv录像,同时进行讯飞声纹认证
由于最近的demo中需要在活体检测的同时进行音视频录制 , 尝试使用MediaRecord和camera来录制视频 , 然而Camera.onPreviewFrame 不能与 MediaRecord ...