共享内存
最为高效的进程间通信方式
进程直接读写内存,不需要任何数据的拷贝
•为了在多个进程间交换信息,内核专门留出了一块内存区
•由需要访问的进程将其映射到自己私有地址空间
•进程直接读写这一内存区而不需要进行数据的拷贝,提高了效率
多个进程共享一段内存,需要依靠某种同步机制,如互斥锁和信号量等
l共享内存编程步骤:
1. 创建共享内存
•函数shmget()
•从内存中获得一段共享内存区域
2. 映射共享内存
•把这段创建的共享内存映射到具体的进程空间中
•函数shmat()
3. 使用这段共享内存
•可以使用不带缓冲的I/O读写命令对其进行操作
4. 撤销映射操作: 函数shmdt()
5. 删除共享内存: 函数shctl()
下面给出几个实例说明上述函数的相关用法。
1.用shmget函数编制一个创建或打开一块新共享内存的函数
#include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> int openshm(int size) { int shmid; if(shmid=shmget(IPC_PRIVATE,size,0)==-1) { printf(" Get shared memory failed!\n"); return -1; } return shmid; }
2.用共享内存实现客户--服务器的通信模式
2.1服务器程序
#include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <stdio.h> #include <string.h> int main() { int shmid; char c; char *shmptr, *s; if((shmid=shmget(1234,256,IPC_CREAT | 0666))<0) { printf("shmget failed.\n"); exit(1); } if((shmptr=shmat(shmid,0,0))==-1) { shmctl(shmid, IPC_RMID, (struct shmid_ds *)shmptr); printf("shmat failed.\n"); exit(2); } s=shmptr; for(c='a';c<='z';c++) *s++=c; *s=NULL; while(*shmptr!='*') sleep(1); shmctl(shmid, IPC_RMID, (struct shmid_ds *)shmptr); return 0; }
2.2客户程序如下:
#include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <stdio.h> #include <string.h> int main() { int shmid; char c; char *shmptr, *s; if((shmid=shmget(1234,256, 0666))<0) { printf("shmget failed.\n"); exit(1); } if((shmptr=shmat(shmid,0,0))==-1) { shmctl(shmid,IPC_RMID,(struct shmid_ds *)shmptr); printf("shmat failed.\n"); exit(2); } for(s=shmptr;*s!=NULL;s++) putchar(*s); printf("\n"); *shmptr='*'; return 0; }
3.当系统调用shmat中的addr取值为0时,共享内存附加到的地址是完全由系统决定的,这个程序测试共享内存附加到的地址
#include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <stdio.h> char array[4000]; int main() { int shmid; char *ptr, *shmptr; printf("array[] form %x to %x \n",&array[0],&array[3999]); printf("stack around %x \n", &shmid); if((ptr=malloc(10000))==NULL) { printf("malloc failed.\n"); exit(1); } if((shmid=shmget(IPC_PRIVATE,10000,SHM_R|SHM_W))<0) { printf("shmget failed.\n"); exit(2); } if((shmptr=shmat(shmid,0,0))==-1) { printf("shmat failed.\n"); exit(3); } printf("shared memory attached from %x to %x \n",shmptr,shmptr-10000); if(shmctl(shmid,IPC_RMID,0)<0) { printf("shmctl failed.\n"); exit(4); } return 0; }