共享内存
- 什么是共享内存
共享内存就是允许两个不相关的进程访问同一个逻辑内存。共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常安排为同一段物理内存。进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像它们是由用C语言函数malloc()分配的内存一样。而如果某个进程向共享内存写入数据,所做的改动将立即影响到可以访问同一段共享内存的任何其他进程。
特别提醒:共享内存并未提供同步机制,也就是说,在第一个进程结束对共享内存的写操作之前,并无自动机制可以阻止第二个进程开始对它进行读取。所以我们通常需要用其他的机制来同步对共享内存的访问,例如前面说到的信号量。 - 共享内存的使用
与信号量一样,在Linux中也提供了一组函数接口用于使用共享内存,而且使用共享共存的接口还与信号量的非常相似,而且比使用信号量的接口来得简单。它们声明在头文件 sys/shm.h 中。- shmget()函数
该函数用来创建共享内存,它的原型为:int shmget(key_t key, size_t size, int shmflg);
成功时返回一个与key相关的共享内存标识符(非负整数),用于后续的共享内存函数。调用失败返回-1. - shmat()函数
第一次创建完共享内存时,它还不能被任何进程访问,shmat()函数的作用就是用来启动对该共享内存的访问,并把共享内存连接到当前进程的地址空间。它的原型如下:void *shmat(int shm_id, const void *shm_addr, int shmflg);
成功时返回一个指向共享内存第一个字节的指针,如果调用失败返回-1. - shmdt()函数
该函数用于将共享内存从当前进程中分离。注意,将共享内存分离并不是删除它,只是使该共享内存对当前进程不再可用。它的原型如下:int shmdt(const void *shmaddr);
调用成功时返回0,失败时返回-1. - shmctl()函数
与信号量的semctl()函数一样,用来控制共享内存,它的原型如下:int shmctl(int shm_id, int command, struct shmid_ds *buf);
- shmget()函数
- 例,进程A shmwrite.c 源码
-
#include <stdlib.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <stdio.h> #include <error.h> #define SHM_SIZE 4096 #define SHM_MODE (SHM_R | SHM_W) /* user read/write */ int main(void) { int shmid; char *shmptr; if ( (shmid = shmget(0x44, SHM_SIZE, SHM_MODE | IPC_CREAT)) < 0) perror("shmget"); if ( (shmptr = shmat(shmid, 0, 0)) == (void *) -1) perror("shmat"); /* 往共享内存写数据 */ sprintf(shmptr, "%s", "hello, world"); exit(0); }
进程B shmread.c 源码
-
#include <stdlib.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <stdio.h> #include <error.h> #define SHM_SIZE 4096 #define SHM_MODE (SHM_R | SHM_W | IPC_CREAT) /* user read/write */ int main(void) { int shmid; char *shmptr; if ( (shmid = shmget(0x44, SHM_SIZE, SHM_MODE | IPC_CREAT)) < 0) perror("shmget"); if ( (shmptr = shmat(shmid, 0, 0)) == (void *) -1) perror("shmat"); /* 从共享内存读数据 */ printf("%s\n", shmptr); exit(0); }
编译
-
-
运行
-