共享内存的本质是让两个进程能够看到一块内存区域,共享内存是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核,也就是说,进程不再通过执行进入内核的系统调用来传递彼此的数据。
获取共享内存的方式和消息队列类似,下面来介绍一下。
shmget函数:用来创建共享内存。
int shmget(key_t key, size_t size, int shmflg); //key共享内存段名字 //size共享内存的大小 //shmflg权限标志,与mode一样 //返回值:成功返回非负整数,失败返回-1
shmat函数:将共享内存映射到进程地址空间
void *shmat(int shmid, const void* shmaddr, int shmflg); //shmid共享内存标识,shmget的返回值 //shmaddr指定连接的地址,一般为NULL,由操作系统自动加载 //shmflg读写权限,一般给0 //返回值:成功返回共享内存第一个地址,失败返回-1
shmdt函数:将共享内存与进程脱离
int shmdt(const void* shmaddr); //shmaddr:由shmat返回的 地址 //返回值:成功返回0,失败返回-1
shmdt函数:控制共享内存
int shmctl(int shmid, int cmd, struct shmid_ds *buf); //buf指向保存共享内存模式状态和访问权限的数据结构
共享内存的确是IPC最快的通信模式,但是却有一个很大,那就是没有同步互斥机制,为了解决这个问题,我们又引入了一个新的资源,叫做信号量。
通过信号量,我们就可以达到既能通信,也不会发生数据不一致的问题。
下来写一个案例: 共享内存通信完整代码
#include"comm.h" //创建共享内存 int main( void ) { key_t key = ftok(PATHNAME, PROJ_ID); if( key < 0){ perror("ftok"); exit(1); } int shmid = shmget(key, sizeof(stu_t), IPC_CREAT|IPC_EXCL|0644); if(shmid < 0){ perror("shmget"); exit(1); } printf("cerate ok\n"); return shmid; printf("create ok\n"); }
进程client,写数据
#include"comm.h" static int commShm(int size, int flags) { key_t key = ftok(PATHNAME, PROJ_ID); if( key < 0){ perror("ftok"); return -1; } int shmid = shmget(key, 36, 0); if(shmid < 0){ perror("shmget"); exit(1); } printf("cerate ok\n"); return shmid; } int getShm(int size) { printf("client get\n"); return commShm(size, 0); } int main() { int shmid = getShm(36); stu_t* addr = (stu_t*)shmat(shmid, NULL, 0); if(NULL == addr){ perror("shmat"); exit(1); } sleep(3); int i = 0; while(1){ sprintf(addr->name,"ABC%d",i); i++; } shmdt(addr); sleep(2); return 0; }
server进程,读数据
#include"comm.h" static int commShm(int size, int flags) { key_t key = ftok(PATHNAME, PROJ_ID); if( key < 0){ perror("ftok"); exit(1); } int shmid = shmget(key, 36, flags); if(shmid < 0){ perror("shmget"); exit(1); } printf("cerate ok\n"); return shmid; } int createShm(int size) { printf("certe\n"); return commShm(size, 0); } int destroyShm(int shmid) { int del = shmctl(shmid, IPC_RMID, NULL); if(del < 0) { perror("shmctl"); exit(19); } return 0; } int main() { int shmid = createShm(36); stu_t* addr = (stu_t*)shmat(shmid, NULL, 0); if(NULL == addr) { perror("shmat"); return -1; } int i = 3; while(i--){ printf("come to while\n"); sleep(1); printf("%s\n",addr->name); } shmdt(addr); sleep(2); printf("Program is over\n"); //destroyShm(shmid); return 0; }
这个代码没有去解决同步互斥的问题,但是通过信号量,是可以解决这个问题的。
文章来源: 共享内存