共享内存通信方式效率最高,毕竟是直接操作内存,但是要保证多个进程对同一块内存访问的同步互斥比较麻烦,借助信号量实现
对每个共享存储段,内核维护一个shmid_ds类型的结构体,定义在<sys/shm.h>文件中
struct shmid_ds { struct ipc_perm shm_perm; //共享内存的ipc_perm结构 size_t shm_segsz; //共享内存区域大小,字节表示 pid_t shm_lpid; //最后一次调用shmop函数的进程ID pid_t shm_cpid; //创建此共享内存的进程ID unsigned short shm_lkcnt; //共享内存被锁定的时间数 unsigned long shm_nattch; //当前使用共享内存的进程数 time_t shm_atime; //最后一次附加操作时间 time_t shm_dtime; //最后一次分离操作时间 time_t shm_ctime; //最后一次修改时间 }
共享内存基本操作
1,创建或打开一个共享内存(shmget)
//create_shm.c #include<sys/types.h> #include<sys/ipc.h> #include<sys/shm.h> #include<stdio.h> #define BUFSZ 1024 int main() { int shm_id; //共享内存ID shm_id = shmget(IPC_PRIVATE,BUFSZ,0666); if(shm_id < 0){ printf("shmget failed\n"); return -1; } printf("create shared memory succeed: %d\n",shm_id); system("ipcs -m"); //查看共享内存ID return 0; }
2,附加共享内存到进程空间(shmat/shmdt)
//attach_shm.c #include<sys/types.h> #include<sys/ipc.h> #include<sys/shm.h> #include<stdio.h> #define BUFSZ 1024 int main() { int *shm; shm = shmat(104529925,NULL,0); if(*shm == -1){ printf("shmat failed\n"); return -1; } printf("attach shared memory succeed: %d\n",*shm); system("ipcs -m"); //查看共享内存调用状态 if(shmdt(shm) == -1){ printf("shmdt failed\n"); return -1; } system("ipcs -m"); //查看共享内存调用状态 return 0; }
3,共享内存控制函数(shmctl)
下面写个简单的例子
共享内存写端(write_shm.c)
//write_shm.c #include<sys/types.h> #include<sys/ipc.h> #include<sys/shm.h> #include<stdio.h> typedef struct { char name[4]; int age; }people; int main() { int i; char *t = 'a'; people *p_shm = NULL; p_shm = shmat(104529925,NULL,0); if(p_shm == NULL){ printf("shmat failed\n"); return -1; } for(i=0;i<5;i++) { t += 1; memcpy((*(p_shm+i)).name,&t,1); (*(p_shm+i)).age = 20+i; } if(shmdt(p_shm) == -1){ printf("shmdt failed\n"); return -1; } return 0; }
共享内存读端(read_shm.c)
//read_shm.c #include<sys/types.h> #include<sys/ipc.h> #include<sys/shm.h> #include<stdio.h> typedef struct { char name[4]; int age; }people; int main() { int i; char *t = 'a'; people *p_shm = NULL; p_shm = shmat(104529925,NULL,0); if(p_shm == NULL){ printf("shmat failed\n"); return -1; } for(i=0;i<5;i++) { printf("name:%s age:%d\n",(*(p_shm+i)).name,(*(p_shm+i)).age); } if(shmdt(p_shm) == -1){ printf("shmdt failed\n"); return -1; } return 0; }
先后编译执行"写代码"与"读代码",结果如下
root$ ./write_shm.out root$ ./read_shm.out name:b age:20 name:c age:21 name:d age:22 name:e age:23 name:f age:24