共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程地址空间,这些进程间数据传递将不在涉及到内核,但任何事都有二义性,它是一个临界资源,但这样的方法却没有给提供任何保护。
如图:
将共享区的代码通过页表映射到不同的PCB下,就可以实现共享内存,
以下为系统调用:
int shmget(key_t key,size_t size,int shflg); //创建共享内存
void* shmat(int shmid,const char* shmaddr,int shmflg); //映射关系
参数:
shmid:共享内存标识符
shmaddr:指定要连接的地址,为NULL时,自动选择一个地址
shmflg:设置共享内存特性,一般为0
返回值:成功返回一个指向共享内存的指针,失败返回-1
int shmdt(const char* shmaddr); //断开映射关系
int shmctl(int shmid,int cmd,struct shmid_da* buf); //控制共享内存
以下是代码实现:
comm.h #pragma once #include<stdio.h> #include<sys/stat.h> #include<sys/types.h> #include<sys/ipc.h> #include<sys/shm.h> #include<unistd.h> #define PATHNAME "." #define PROJ_ID 0x6666 int createShm(int size); int destoryShm(int shmid); int getShm(int size);
comm.c #include<stdio.h> #include"comm.h" static int commShm(int size,int flags) { key_t k = ftok(PATHNAME,PROJ_ID); if (k<0) { perror("ftok"); return -1; } int shmid = 0; if((shmid = shmget(k,size,flags)) < 0) { perror("shmget"); return -2; } return shmid; } int destoryShm(int shmid) { if(shmctl(shmid,IPC_RMID,NULL) < 0) { perror("shmctl"); return -1; } return 0; } int createShm(int size) { return commShm(size,IPC_CREAT|IPC_EXCL|0666); } int getShm(int size) { return commShm(size,IPC_CREAT); }
server.c #include<stdio.h> #include"comm.h" int main() { int shmid = createShm(4096); char *addr = shmat(shmid,NULL,0); sleep(2); int i = 0; while(i++ < 26) { printf("Client# %s\n",addr); sleep(1); } shmdt(addr); sleep(2); destoryShm(shmid); return 0; }
client.c #include<stdio.h> #include"comm.h" int main() { int shmid = getShm(4096); sleep(1); char* addr = shmat(shmid,NULL,0); sleep(2); int i = 0; while(i < 26) { addr[i] = 'A' +i; i++; addr[i] = 0; sleep(1); } shmdt(addr); sleep(2); return 0; }
结果可以自己实验一下,但是和消息队列一样,它的生命周期也是随内核,故需要用
ipcs -m //查看 ipcrm -m//删除 IPC资源