当前位置: 首页 >> 程序设计 >> Linux 进程间通信: 共享内存(下)
 

Linux 进程间通信: 共享内存(下)

作者:      来源:zz     发表时间:2008-04-14     浏览次数:      字号:    



4、系统V共享内存范例

本部分将给出系统V共享内存API的使用方法,并对比分析系统V共享内存机制与mmap()映射普通文件实现共享内存之间的差异,首先给出两个进程通过系统V共享内存通信的范例:

/***** testwrite.c *******/
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
typedef struct{
 char name[4];
 int age;
} people;
main(int argc, char** argv)
{
 int shm_id,i;
 key_t key;
 char temp;
 people *p_map;
 char* name = "/dev/shm/myshm2";
 key = ftok(name,0);
 if(key==-1)
  perror("ftok error");
 shm_id=shmget(key,4096,IPC_CREAT); 
 if(shm_id==-1)
 {
  perror("shmget error");
  return;
 }
 p_map=(people*)shmat(shm_id,NULL,0);
 temp='a';
 for(i = 0;i<10;i++)
 {
  temp+=1;
  memcpy((*(p_map+i)).name,&temp,1);
  (*(p_map+i)).age=20+i;
 }
 if(shmdt(p_map)==-1)
  perror(" detach error ");
}
/********** testread.c ************/
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <unistd.h>
typedef struct{
 char name[4];
 int age;
} people;
main(int argc, char** argv)
{
 int shm_id,i;
 key_t key;
 people *p_map;
 char* name = "/dev/shm/myshm2";
 key = ftok(name,0);
 if(key == -1)
  perror("ftok error");
 shm_id = shmget(key,4096,IPC_CREAT); 
 if(shm_id == -1)
 {
  perror("shmget error");
  return;
 }
 p_map = (people*)shmat(shm_id,NULL,0);
 for(i = 0;i<10;i++)
 {
 printf( "name:%s\n",(*(p_map+i)).name );
 printf( "age %d\n",(*(p_map+i)).age );
 }
 if(shmdt(p_map) == -1)
  perror(" detach error ");
}

testwrite.c创建一个系统V共享内存区,并在其中写入格式化数据;testread.c访问同一个系统V共享内存区,读出其中的格式化数据。分别把两个程序编译为testwrite及 testread,先后执行./testwrite及./testread 则./testread输出结果如下:

name: b age 20; name: c age 21; name: d age 22; name: e age 23; name: f age 24;
name: g age 25; name: h age 26; name: I age 27; name: j age 28; name: k age 29;

通过对试验结果分析,对比系统V与mmap()映射普通文件实现共享内存通信,可以得出如下结论:

1、 系统V共享内存中的数据,从来不写入到实际磁盘文件中去;而通过mmap()映射普通文件实现的共享内存通信可以指定何时将数据写入磁盘文件中。注:前面讲到,系统V共享内存机制实际是通过映射特殊文件系统shm中的文件实现的,文件系统shm的安装点在交换分区上,系统重新引导后,所有的内容都丢失。

2、 系统V共享内存是随内核持续的,即使所有访问共享内存的进程都已经正常终止,共享内存区仍然存在(除非显式删除共享内存),在内核重新引导之前,对该共享内存区域的任何改写操作都将一直保留。

3、 通过调用mmap()映射普通文件进行进程间通信时,一定要注意考虑进程何时终止对通信的影响。而通过系统V共享内存实现通信的进程则不然。注:这里没有给出shmctl的使用范例,原理与消息队列大同小异。






结论:

共享内存允许两个或多个进程共享一给定的存储区,因为数据不需要来回复制,所以是最快的一种进程间通信机制。共享内存可以通过mmap()映射普通文件(特殊情况下还可以采用匿名映射)机制实现,也可以通过系统V共享内存机制实现。应用接口和原理很简单,内部机制复杂。为了实现更安全通信,往往还与信号灯等同步机制共同使用。

共享内存涉及到了存储管理以及文件系统等方面的知识,深入理解其内部机制有一定的难度,关键还要紧紧抓住内核使用的重要数据结构。系统V共享内存是以文件的形式组织在特殊文件系统shm中的。通过shmget可以创建或获得共享内存的标识符。取得共享内存标识符后,要通过shmat将这个内存区映射到本进程的虚拟地址空间。



参考资料

[1] Understanding the Linux Kernel, 2nd Edition, By Daniel P. Bovet, Marco Cesati , 对各主题阐述得重点突出,脉络清晰。

[2] UNIX网络编程第二卷:进程间通信,作者:W.Richard Stevens,译者:杨继张,清华大学出版社。对mmap()有详细阐述。

[3] Linux内核源代码情景分析(上),毛德操、胡希明著,浙江大学出版社,给出了mmap()相关的源代码分析。

[4]shmget、shmat、shmctl、shmdt手册



关于作者

郑彦兴,国防科大攻读博士学位。联系方式: mlinux@163.com

[1] [2]

编辑 webmaster

发表评论  打印本文  推荐本文  加入收藏  返回顶部  关闭窗口
 
 
 
评论更多>>
 
 
发表
 
姓名: QQ:
性别: MSN:
E-mail: 主页:
评分: 1 2 3 4 5
评论内容:
验证码:
  
  • 请遵守《互联网电子公告服务管理规定》及中华人民共和国其他各项有关法律法规。
  • 严禁发表危害国家安全、损害国家利益、破坏民族团结、破坏国家宗教政策、破坏社会稳定、侮辱、诽谤、教唆、淫秽等内容的评论 。
  • 用户需对自己在使用本站服务过程中的行为承担法律责任(直接或间接导致的)。
  • 本站管理员有权保留或删除评论内容。
  • 评论内容只代表网友个人观点,与本网站立场无关。
  •