标签:linux进程间通信 共享内存
共享内存是最高效的IPC机制,因为它不涉及进程之间的任何数据传输。这种高效带来的问题是,我们必须使用其他辅助手段来同步进程对内存的访问,否则会产生竞态条件(一般我们与信号量结合使用)。因此,共享内存通常和其他进程间通信方式一起使用。
Linux共享内存的API都定义在sys/shm.h头文件中,包括4个系统调用:shmget、shmat、shmdt和shmctl
#include <sys/shm.h> int sys_shmget (key_t key, int size, int shmflg); void *shmat(int shmid, const void *shmaddr, int shmflg); int sys_shmdt (char *shmaddr); int shmctl(int shmid,int cmd,struct shmid_ds *buf);
l shmget系统调用创建一段新的共享内存,或者获取一段已经存在的共享内存。
和shmget系统调用一样,key参数是一个键值,用来标识一段全局唯一的共享内存。size参数指定共享的大小,单位是字节。如果是创建新的共享内存,则size值必须被指定。如果是获取已经存在的共享内存,则可以把size设置为0。
shmflg参数的使用和含义与semget系统调用的semflag参数相同
shmget成功时返回一个正整数,它是共享内存的标识符。shmget失败时返回-1,并设置errno。如果shmget用于创建共享内存,则这段共享内存的所有字节都被初始化为0,与之关联的内核数据结构shmid_ds将被创建并初始化。
l shmat和shmdt用于关联/分离共享内存,共享内存被创建/获取后,我们不能立即访问它,需要先将它关联到进程的地址空间中,使用完后,再从地址空间分离。
其中shmid参数是由shmget调用返回的共享内存标识符。shmaddr参数指定共享内存关联到进程的哪块地址空间,最终的效果还是受到shmflg参数的可选标志SHM_RND的影响:
如果shmaddr为NULL,则被关联的地址由操作系统选择。这是推荐的做法,以确保可移植性。
l shmctl用于控制共享内存的某些属性,shmid参数是由shmget调用返回的共享内存标识符。cmd参数指定要执行的命令。shmctl成功时的返回值取决于cmd参数,失败时返回-1,并设置errno。
共享内存程序示例
#include <sys/sem.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> #define err_sys(msg) do { perror(msg); exit(-1); } while(0) union semun { int val; struct semid_ds *buf; unsigned short int *array; struct seminfo * __buf; }; void pv(int sem_id, int op) { struct sembuf sem_b; sem_b.sem_num = 0; sem_b.sem_op = op; sem_b.sem_flg = SEM_UNDO; semop(sem_id, &sem_b, 1); } int main(void) { int sem_id = semget(IPC_PRIVATE, 1, 0666); int shm_id = shmget(IPC_PRIVATE, 4, 0666); union semun sem_un; sem_un.val = 1; semctl(sem_id, 0, SETVAL, sem_un); pid_t pid = fork(); if(pid < 0) err_sys("fork"); else if(pid == 0) { char *shmp; pv(sem_id, -1); shmp = shmat(shm_id, NULL, 0); if(shmp == (char *)(-1)) err_sys("child shmat"); *(int *)shmp = 10; shmdt(shmp); printf("child get the sem and would sleep 2s.\n"); sleep(2); pv(sem_id, 1); exit(0); } else { char *shmp; sleep(1); pv(sem_id, -1); shmp = shmat(shm_id, NULL, 0); if(shmp == (char *)(-1)) err_sys("child shmat"); printf("shm: %d\n", *(int *)shmp); shmdt(shmp); printf("parent get the sem and would sleep 2s.\n"); sleep(2); pv(sem_id, 1); } waitpid(pid, NULL, 0); shmctl(shm_id, IPC_RMID, NULL); semctl(sem_id, 0, IPC_RMID, sem_un); return 0; }
1、《Linux高性能服务器编程》 第13章 多进程编程/共享内存
2、Linux 进程间通信 - 共享内存 (这个讲的比较详细....)
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:linux进程间通信 共享内存
原文地址:http://blog.csdn.net/u012796139/article/details/46692787