共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC通信形式。是针对其他通信机制运行效率较低而设计的,往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。
机制如下:
特点:
1.内存共享是进程间通信速度最快的:
由上图可知,内存共享是进程1从其地址空间直接写到物理内存中,进程2则直接通过地址空间虚拟地址从内存中取,不需要通过进入内核来传递消息,而消息队列,信号量则都要在内核开辟一块空间,进程通信传递需从用户区拷贝到内核区,再从内核区拷贝到用户区,所以其不涉及内核的拷贝,所以其效率较高。
2.共享内存不带任何同步、互斥机制,所以其一般都与信号量匹配使用;
3.共享内存开辟在物理内存上,所以其生命周期为随内核。
Linux下共享内存的两条命令:
ipcs -m ; //查看共享内存 ipcrm -m <shmid>; //删除共享内存
1.创建共享内存:
函数:
int shmget(key_t key,size_t size,int shmflag);参数:
key:共享内存唯一的键值,用ftok()函数获取;
size:申请的内存大小,一般为页的整数倍,因为系统分配的大小始终为页的整数倍,1页=4k;
shmflag:IPC_CREAT(单独使用没有创建共享内存,创建新的共享内存,若有,则返回存在的共享内存),IPC_EXCL(与IPC_CREAT合用,不存在,创建新的,存在返回错误码);
返回值:
成功返回共享内存id,失败返回错误码。
2.删除共享内存:
函数:
int shmctl(int shmid,int cmd,struct shmid_ds* buf);参数:
shmid:共享内存id;
cmd:删除时设为IPC_IMID;
buf:对共享内存的修改或对其查看,若cmd设为IPC_IMID,则设为NULL;
3.共享内存的挂接:
函数:(此函数用法与malloc()相同)
void* shmat(int shmid,const void* shmaddr,int shmflg);参数:
shmid:共享内存id;
shmaddr:共享内存与指定虚拟地址建立映射关系,一般设为NULL,即由操作系统安排;
shmflg:一般设为缺省0;
返回值:
建立映射关系后返回的虚拟地址。
4.与共享内存断开联系:
函数:
int shmdt(const void* shmaddr);参数:
shmaddr:shmat()函数的返回值虚拟地址;
代码实现:
comm.h
#ifndef _COMM_H__ #define _COMM_H__ #include <stdio.h> #include <sys/ipc.h> #include <sys/shm.h> #include <unistd.h> #define PATH "." #define PROJ_ID 0x6666 int creatShm(int size); //创建 int getShm(int size); //获取 int destroyShm(int shmid); //删除 #endif //_COMM_H__
server.c(读打印)
#include "comm.h" int main() { int shmid=creatShm(4096); //创建共享内存 //printf("create success!!! shmid:%d\n",shmid); sleep(3); char* addr=shmat(shmid,NULL,0); //使当前进程与共享内存挂接 ,此函数返回进程虚拟地址 int i=0; //第二个参数为指定的虚拟地址,一般由操作系统指定,所以设为null while(i<26) { printf("%s\n",addr); //打印地址(读共享内存处内容)处内容 sleep(1); ++i; } shmdt(addr); //使当前进程与共享内存断开关联 int ret=destroyShm(shmid); //printf("destroy success. ret:%d\n",ret); return 0; }
#include "comm.h" int main() { int shmid=getShm(4096); //获取已创建好的共享内存 printf("getShm success!! shmid:%d\n",shmid); char* addr=shmat(shmid,NULL,0); //使当前进程与共享内存挂接 ,此函数返回进程虚拟地址 int i=0; while(i<26) { addr[i]='A'+i; //向共性内存处写内容 sleep(1); ++i; addr[i]=0; } shmdt(addr); //使当前进程与共享内存断开关联 return 0; }comm.c
#include "comm.h" static int commShm(int size,int flags) { key_t _key=ftok(PATH,PROJ_ID); if(_key<0) { perror("ftok"); return -1; } int shmid=shmget(_key,size,flags); //创建或获取共享内存 参数size为页的整数倍(会自动调整) 1页=4k if(shmid<0) { perror("shmget"); return -2; } return shmid; } int creatShm(int size) { return commShm(size,IPC_CREAT|IPC_EXCL|0666); } int getShm(int size) { return commShm(size,IPC_CREAT); } int destroyShm(int shmid) { if(shmctl(shmid,IPC_RMID,NULL)<0) //立即删除shmid标识的共享内存 { perror("destroy:shmctl"); return -1; } return 0; }