共享内存是进程间通信的一种最基本、最快速的机制。共享内存是两个或多个进程共享同一块内存区域,并通过该内存区域实现数据交换的进程间通信机制。通常是由一个进程开辟一块共享内存区域,然后允许多个进程对此区域进行访问。由于不需要使用中间介质,而是数据由内存直接映射到进程空间,因此共享内存是最快速的进程间通信机制。
共享内存的最大不足之处在于,由于多个进程对同一块内存区具有访问的权限,各个进程之间的同步问题显得尤为突出。必须控制同一时刻只有一个进程对共享内存区域写入数据,否则将造成数据的混乱。但是同步控制的问题,可以通过信号量解决。
一、System V 共享内存
1、获取key值
Linux系统建立IPC通讯(如消息队列、共享内存时)必须指定一个ID值。通常情况下,该id值通过ftok函数得到。
#include <sys/shm.h>
#include <sys/types.h>
key_t ftok( char * fname, int id )
2、新建/获取共享内存
用来创建一块共享内存并返回其 id 或者获得一块已经被创建的共享内存的 id
#include <sys/shm.h>
int shmget (key_t key, size_t size, int shmflag);
3、控制共享内存
用来创建一块共享内存并返回其 id 或者获得一块已经被创建的共享内存的 id
//from /usr/include/sys/shm.h
int shmctl(int shmid,int cmd,struct shmid_ds* buf);
4、共享内存映射
将共享内存映射到当前进程,映射调用成功后, 会修改 shmid_ds
的部分字段:
- 将 shm_nattach 加一
- 将 shm_lpid 设置为调用进程 pid
- 将 shm_atime 设置为当前时间
//from /usr/include/sys/shm.h
void * shmat(int shmid,void* shmaddr,int flag);
5、分离共享内存
当一个进程对共享内存区域的访问完成后,可以调用 shmdt 函数使共享内存区域与该进程的地址空间分离。调用成功时修改内核数据结构 shmid_ds
部分字段:
- 将 shm_nattach 减一
- 将 shm_lpid 设置为调用进程的pid
- 将 shm_dtime 设置为当前时间
注意,调用 shmdt 并不会删除共享内存
#include <sys/shm.h>
int shmdt ( const void* shm_addr );