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 ...
随机推荐
- linux系统下调度数据库类型资源库中的kettle job
已经存在kettle的一个资源库enfo,在目录/works/wxj下面有一个job (testmailsuccess.kjb)如何实现手工在kettle外部执行此job和让系统每天定时的调用此job ...
- 深入剖析Android音频之AudioTrack
播放声音能够用MediaPlayer和AudioTrack,两者都提供了java API供应用开发人员使用.尽管都能够播放声音.但两者还是有非常大的差别的.当中最大的差别是MediaPlayer能够播 ...
- 为什么要使用href=”javascript:void(0);”?
JavaScript中语句最后的分号是可以缺省的,那为何要使用javascript:;而不是javascript:呢? 是习惯还是规范,我疑惑了! 具有代码洁癖的coder们,没事多写一个分号,圣洁的 ...
- (LeetCode74)Search a 2D Matrix
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the follo ...
- linux下线刷硬盘
Linux系统往往有添加磁盘不够的情况,这时就需要添加新的硬盘.一般情况下需要重启服务器,这里我们来使用线刷方式读取Linux新增硬盘 1.添加磁盘后fdisk -l磁盘没有显示 2.查看主机总线号 ...
- Python面向对象编程 - 一个记事本程序范例(一)
notebook.py import datetime last_id = 0 class Note: '''Represent a note in the notebook. Match again ...
- jQuery之前端国际化jQuery.i18n.properties[转]
http://www.ibm.com/developerworks/cn/web/1305_hezj_jqueryi18n/ jQuery.i18n.properties是一款轻量级的jQuery国际 ...
- TQ2440烧写方法总结
USB烧写 接线:需要连接串口线.USB下载线和电源线. 软件:USB转串口驱动(因为现在的笔记本上一般都没有串口).USB下载驱动和DNW. 网络烧写 接线:需要连接串口线.网线和电源线. 软件:T ...
- bzoj3675【APIO2014】序列切割
3675: [Apio2014]序列切割 Time Limit: 40 Sec Memory Limit: 128 MB Submit: 1468 Solved: 607 [Submit][Sta ...
- MySQL 数据库几种类型
关系数据库(MySQL.Oracle.SQL Server.DB2.Postgres)键-值存储数据库(Riak和Redis)面向列的数据库(HBase) 面向文档的数据库(MongoDB 和Couc ...