Linux 进程间通信 共享内存
来源:互联网 发布:vs mysql 编辑:程序博客网 时间:2024/05/18 01:14
共享内存可以说是最有用的进程间通信方式,也是最快的 IPC 形式。两个不同进程 A、B 共享内存的意思是,同一块物理内存被映射到进程 A、B 各自的进程地址空间。进程 A 可以即时看到进程 B 对共享内存中数据的更新,反之亦然。由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以。
采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝。对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次数据[1]:一次从输入文件到共享内存区,另一次从共享内存区到输出文件。
实际上,进程之间在共享内存时,并不总是读写少量数据后就解除映射,有新的通信时,再重新建立共享内存区域。而是保持共享区域,直到通信完毕为止,这样,数据内容一直保存在共享内存中,并没有写回文件。共享内存中的内容往往是在解除映射时才写回文件的。因此,采用共享内存的通信方式效率是非常高的。
mmap()系统调用
1:两个进程通过映射普通文件实现共享内存通信
#include <sys/mman.h>#include <sys/types.h>#include <fcntl.h>#include <unistd.h>typedef struct{ char name[4]; int age;}people;int main(int argc,char **argv){ int fd,i; people *p_map; char temp; fd=open(argv[1],O_CREAT|O_RDWR|O_TRUNC,00777); lseek(fd,sizeof(people)*5-1,SEEK_SET); write(fd,"",1); p_map=(people*)mmap(NULL,sizeof(people)*10,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0); close(fd); temp='a'; for(i=0;i<10;i++){ temp+=1; memcpy((*(p_map+i)).name,&temp,2); (*(p_map+i)).age=20+i; } printf("initialize over\n"); sleep(10); munmap(p_map,sizeof(people)*10); printf("umap ok\n"); return 0;}
#include <sys/mman.h>#include <sys/types.h>#include <fcntl.h>#include <unistd.h>typedef struct{ char name[4]; int age;}people;int main(int argc,char**argv){ int fd,i; people *p_map; fd=open(argv[1],O_CREAT|O_RDWR,00777); p_map=(people*)mmap(NULL,sizeof(people)*10,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0); for(i=0;i<10;i++){ printf("%d,name:%s,age:%d\n",i+1,(*(p_map+i)).name,(*(p_map+i)).age); } munmap(p_map,sizeof(people)*10); return 0;}
2:父子进程通过匿名映射实现共享内存
#include <sys/mman.h>#include <sys/types.h>#include <fcntl.h>#include <unistd.h>typedef struct { char name[4]; int age;}people;int main(){ int i; people *p_map; char temp; pid_t pid; p_map=(people*)mmap(NULL,sizeof(people)*10,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0); if((pid=fork())<0){ printf("fork error\n"); }else if(pid>0){ temp='a'; for(i=0;i<5;i++){ temp+=1; memcpy((*(p_map+i)).name,&temp,2); (*(p_map+i)).age=20+i; } sleep(5); printf("P read:%d\n",(*p_map).age); printf("umap\n"); munmap(p_map,sizeof(people)*10); printf("umap ok\n"); exit(0); }else{ sleep(2); for(i=0;i<5;i++){ printf("c read %d,name:%s,age:%d\n",i+1,(*(p_map+i)).name,(*(p_map+i)).age); } (*p_map).age=100; munmap(p_map,sizeof(people)*10); exit(0); } return 0;}
System V 共享内存
放共享数据的物理内存页面。
系统调用 mmap()通过映射一个普通文件实现共享内存。
system V 则是通过映射特殊文件系统 shm 中的文件实现进程间的共享内存通信。也就是说,每个共享内存区域对应特殊文件系统shm 中的一个文件。
system_v_shm_w.c
#include <sys/ipc.h>#include <sys/shm.h>#include <sys/types.h>#include <unistd.h>typedef struct { char name[4]; int age;}people;int main(){ int shm_id,i; key_t key; char temp; people* p_map; char* name="/home/archermind/Desktop/ritter"; char name2[40]; strcpy(name2,"/dev/shm/ritter"); if((key=ftok("/dev/shm/myshm",1))==-1){ printf("ftok error\n"); exit(0); } if((shm_id=shmget(key,4096,IPC_CREAT))<0){ printf("shmget error\n"); exit(0); } p_map=(people*)shmat(shm_id,NULL,0); temp='a'; for(i=0;i<5;i++){ temp+=1; memcpy((*(p_map+i)).name,&temp,1); (*(p_map+i)).age=20+i; } if(shmdt(p_map)<0){ printf("detach error\n"); exit(0); } return 0;}
system_v_shm_r.c
#include <sys/ipc.h>#include <sys/shm.h>#include <sys/types.h>#include <unistd.h>typedef struct{ char name[4]; int age;}people;int main(){ int shm_id,i; key_t key; people* p_map; char *name="/dev/shm/ritter"; if((key=ftok(name,0))<0){ printf("ftok error\n"); exit(0); } if((shm_id=shmget(key,4096,IPC_CREAT))<0){ printf("shmget error\n"); exit(0); } p_map=(people*)shmat(shm_id,NULL,0); for(i=0;i<5;i++){ printf("%d,name:%s,age:%d\n",i+1,(*(p_map+i)).name,(*(p_map+i)).age); } if(shmdt(p_map)<0){ printf("detach error\n"); } return 0;}参考郑彦兴《Linux进程通信》
消息队列和管道基本上都是4次拷贝,而共享内存(mmap, shmget)只有两次。
4次:1,由用户空间的buf中将数据拷贝到内核中。2,内核将数据拷贝到内存中。3,内存到内核。4,内核到用户空间的buf.
2次: 1,用户空间到内存。 2,内存到用户空间。
消息队列和管道都是内核对象,所执行的操作也都是系统调用,而这些数据最终是要存储在内存中执行的。因此不可避免的要经过4次数据的拷贝。但是共享内存不同,当执行mmap或者shmget时,会在内存中开辟空间,然后再将这块空间映射到用户进程的虚拟地址空间中,即返回值为一个指向一个内存地址的指针。当用户使用这个指针时,例如赋值操作,会引起一个从虚拟地址到物理地址的转化,会将数据直接写入对应的物理内存中,省去了拷贝到内核中的过程。当读取数据时,也是类似的过程,因此总共有两次数据拷贝。
- Linux环境进程间通信: 共享内存
- Linux环境进程间通信:共享内存
- linux环境进程间通信:共享内存
- Linux环境进程间通信: 共享内存
- Linux环境进程间通信 共享内存
- linux进程间通信方式 -- 共享内存
- Linux 进程间通信:共享内存
- Linux环境进程间通信: 共享内存
- Linux环境进程间通信: 共享内存
- linux进程间通信之共享内存
- linux进程间通信之共享内存
- linux进程间共享内存通信详解
- Linux进程间通信 共享内存
- Linux 进程间通信:共享内存(上)
- Linux 进程间通信: 共享内存(下)
- Linux环境进程间通信---共享内存
- Linux进程间通信 共享内存
- Linux环境进程间通信-共享内存
- Extjs光标
- CODE 7: Word Ladder
- Firefox专属hack的写法
- 明日歌
- os.walk使用详解
- Linux 进程间通信 共享内存
- 大家好,我来了
- FindWindow用法
- OMAPL138开发板SD系统启动卡制作方法
- PostgreSQL从菜鸟到专家 什么是数据库管理系统
- 面试需要掌握的排序 Quick Sort and Merge Sort 快速排序和归并排序 [Java]
- IOS详解TableView——实现九宫格效果
- Java开发环境的建立(Windows)
- linux tr 命令详解