LINUX进程间通信之共享存储讲解,linux进程通信讲解
LINUX进程间通信之共享存储讲解,linux进程通信讲解
LINUX进程间通信
一、匿名管道与命名管道
二、消息队列
三、共享存储
共享存储概述:
共享存储允许两个或更多进程共享一给定的存储区。共享内存区是最快的IPC形式,一旦这样的内存映射到共享它的进程的 地址空间,这些进程间数据传递不再涉及到内核,也就是说进程不再需要切换到内核态来传递数据。所以比起消息队列一直在用户态和内核态的切换,共享存储更高效。
相关命令:
ipcs -m :查看当前内核中的共享内存段;
ipcrm -m +shmid :删除对应shmid的共享内存段
共享内存示意图:
也就是说:进程同时拿到同一片共享存储区的shmid,使用shmat将对应的共享存储空间连接到自己的进程地址空间,在进行操作完成之后,再使用shmdt断开连接。在整体使用过程中不需要多次进行状态切换。
共享内存数据结构:
函数介绍:
一、shmget:获得共享存储标识符
#include#include int shmget(key_t key, size_t size, int shmflg); //返回值:成功返回共享内存的标识符,失败返回-1
参数介绍:
①key:与消息队列相同,都是由ftok函数生成;
②size:共享内存大小(单位/字节);通常将其向上取为系统页长的整数倍;
③shmflg:用法和创建文件使用的mode模式标志一样。可参考消息队列中的介绍。
二、shmctl: 控制共享内存
#include#include int shmctl(int shmid, int cmd, struct shmid_ds *buf); //成功返回0,失败返回-1
参数介绍:
①shmid:需要进行操作的共享内存标识码;
②cmd:需要进行的操作(分为IPC_STAT,IPC_SET,IPC_RMID)
③buf:一个指向shmid_ds结构体类型的结构体指针,当参数为IPC_STAT和IPC_SET时,需要给定一个结构体,用来指定修改的值。
三、shmat:将共享内存段连接到进程地址空间
#include#include void *shmat(int shmid, const void *shmaddr, int shmflg); //返回值:成功返回指向共享内存第一个字节的指针,失败返回-1
参数介绍:
①shmid:之前由ftok生成的共享内存标识符;
②shmaddr:指定连接的地址;
③shmflg:可取SHM_RND和SHM_RDONLY
shmaddr取值为NULL,内核自动选择一个地址 shmaddr不为NULL,且shmflg无SHM_RND标记,则以shmaddr为连接地址; shmaddr不为NULL,且shmflg设置了SHM_RND标记,则连接的地址会自动向下调整为SHMLBA的整数倍 shmflg = SHM_RDONLY:表示连接操作用来只读共享内存。
注:更详细的介绍可自行man或查看《unix环境高级编程》
四、shmdt:将共享内存段与当前进程脱离
#include#include void *shmat(int shmid, const void *shmaddr, int shmflg); int shmdt(const void *shmaddr); //返回值:成功返回0,失败返回-1
参数介绍:
shmaddr:由shmat所返回的指针。
注意:
1、共享内存无同步互斥机制!!
2、共享内存段随内核,所以我们最好是在进程结束之前不再使用时,就断开与共享内存的连接。
示例:通过一片共享内存存储区,client向其中写数据,server读取数据并打印到屏幕上。
/**********comm.h*************/ #pragma once #include#include #include #include #define PATHNAME "." #define PROJ_ID 0x66 int createShm(int size); int destroyShm(int shmid); int getShm(int size); /**********comm.c**********/ #include "comm.h" int commShm(int size, int flags) { key_t key = ftok(PATHNAME, PROJ_ID); if(key < 0){ perror("ftok"); return -1; } int shmid = shmget(key, size, flags); if(shmid < 0){ perror("shmget"); return -2; } return shmid; } int destroyShm(int shmid) { if(shmctl(shmid, IPC_RMID, NULL) < 0){ perror("shmctl"); return -1; } return 0; } int creatShm(int size) { return commShm(size, IPC_CREAT | IPC_EXCL | 0666); } int getShm(int size) { return commShm(size, IPC_CREAT); } /**********client.c********/ #include "comm.h" int main() { int shmid = getShm(4094); char* addr = shmat(shmid, NULL, 0); sleep(1); int i = 0; while(i < 5){ addr[i] = 'A' +i; i++; addr[i] = 0; sleep(1); } shmdt(addr); sleep(2); return 0; } /*********server.c*******/ #include "comm.h" int main() { int shmid = creatShm(4096); char* addr = (char*)shmat(shmid, NULL, 0); sleep(5); int i = 0; while(i < 10){ i++; printf("client> %s\n",addr); sleep(1); } shmdt(addr); sleep(2); destroyShm(shmid); return 0; } /*******Makefile********/ .PHONY : all all : server client server : server.c comm.c gcc $^ -o $@ client : client.c comm.c gcc $^ -o $@ .PHONY : clean clean: rm server client
评论暂时关闭