一,概述 系统调用mmap通过映射一个普通文件实现共享内存。SystemV则是通过映射特殊文件系统shm中的文件实现进程间的共享内存通信。也就是说,每个共享内存区域对应特殊文件系统shm中的一个文件。执行过程是先调用shmget,再调用shmat。对于每个共享的内存区,内核维护如下的信息结构,定义在头文件中。structshmidds{structipcpermshmperm;operationpermsintshmsegsz;sizeofsegment(bytes)timetshmatime;lastattachtimetimetshmdtime;lastdetachtimetimetshmctime;lastchangetimeunsignedshortshmcpid;pidofcreatorunsignedshortshmlpid;pidoflastoperatorshortshmnattch;no。ofcurrentattachesthefollowingareprivateunsignedshortshmnpages;sizeofsegment(pages)unsignedlongshmpages;arrayofptrstoframesSHMMAXstructvmareastructattaches;descriptorsforattaches};二、SystemV共享内存区API 使用共享内存的流程:1。进程必须首先分配它。2。随后需要访问这个共享内存块的每一个进程都必须将这个共享内存块绑定到自己的地址空间中。3。当完成通信之后,所有进程都将脱离共享内存,并且由一个进程释放该共享内存块。includesysipc。hincludesysshm。h创建一个新的内存共享区或者访问一个已经存在的共享内存区返回共享内存区标识符intshmget(keytkey,sizetsize,intshmflg);创建或打开一个共享内存区后,调用shmat把它连接到调用进程的地址空间voidshmat(intshmid,constvoidshmaddr,intshmflg);当一个进程完成某个共享内存区的使用时,调用shmdt断开这个内存区intshmdt(constvoidshmaddr);对内存区进行多种操作cmd取值:IPCRMID:从系统中删除由shmid标识的共享内存区并拆除它IPCSET:给指定的共享内存区设置其shmidds结果成员IPCSTAT:通过buff参数向调用者返回所指定共享内存区当前的shmidds结构intshmctl(intshmid,intcmd,structshmiddsbuf); 调用SystemVAPI编写程序进行测试: 程序1:调用shmget函数使用指定的路径名和长度创建一个共享内存区,程序如下:includestdio。hincludestdlib。hincludeunistd。hincludesysshm。hincludefcntl。hdefineSVSHMMODE(SHMRSHMWSHMR3SHMR6)intmain(intargc,charargv〔〕){intc,id,oflag;charptr;sizetlength;oflagSVSHMMODEIPCCREAT;while((cgetopt(argc,argv,e))!1){switch(c){casee:oflagOEXCL;break;}}if(optind!argc2){printf(usage:shmget〔e〕pathnamelength。);exit(0);}lengthatoi(argv〔optind1〕);创建由用户指定其名字和大小的共享内存区idshmget(ftok(argv〔optind〕,0),length,oflag);把该内存区连接到当前进程的地址空间ptrshmat(id,NULL,0);exit(0);} 程序2:调用shmctl指定IPCRMID命令,从系统中删除一个共享内存区,程序如下:includestdio。hincludestdlib。hincludeunistd。hincludesysshm。hdefineSVSHMMODE(SHMRSHMWSHMR3SHMR6)intmain(intargc,charargv〔〕){intid;if(argc!2){printf(usage:shmrmidpathname);exit(0);}打开共享内存区idshmget(ftok(argv〔1〕,0),0,SVSHMMODE);从系统中删除由id标识的共享内存区shmctl(id,IPCRMID,NULL);exit(0);} 程序3:往共享内存区中写入一个模式,调用shmctl指定IPCSTAT命令格式,程序如下:includestdio。hincludestdlib。hincludeunistd。hincludesysshm。hincludefcntl。hdefineSVSHMMODE(SHMRSHMWSHMR3SHMR6)intmain(intargc,charargv〔〕){inti,id;structshmiddsbuff;unsignedcharptr;if(argc!2){printf(usage:shmwritepathname。);exit(0);}idshmget(ftok(argv〔1〕,0),0,SVSHMMODE);ptrshmat(id,NULL,0);shmctl(id,IPCSTAT,buff);获取共享内存区大小for(i0;ibuff。shmsegsz;i)ptri256;exit(0);} 程序4:从共享内存中读出模式,程序如下:includestdio。hincludestdlib。hincludeunistd。hincludesysshm。hincludefcntl。hdefineSVSHMMODE(SHMRSHMWSHMR3SHMR6)intmain(intargc,charargv〔〕){inti,id;structshmiddsbuff;unsignedcharc,ptr;if(argc!2){printf(usage:shmreadpathname。);exit(0);}idshmget(ftok(argv〔1〕,0),0,SVSHMMODE);ptrshmat(id,NULL,0);shmctl(id,IPCSTAT,buff);for(i0;ibuff。shmsegsz;i){cptr;printf(ptr〔d〕d,i,c);}exit(0);}三,SystemV与Posix共享内存区 二者的差别是: (1)Posix共享内存区是先调用shmopen然后再调用mmap,SystemV共享内存区是先调用shmget再调用shmat。 (2)Posix共享内存区对象的大小可在任何时刻通过ftruncate修改,而SystemV共享内存区对象的大小是在调用shmget创建时固定下来的。 更多Linux内核视频教程文档资料免费领取后台私信【内核】自行获取。