共享内存
1.共享内存的概念
共享内存指 (shared memory)在多处理器的计算机系统中,可以被不同中央处理器(CPU)访问的大容量内存。由于多个CPU需要快速访问存储器,这样就要对存储器进行缓存(Cache)。任何一个缓存的数据被更新后,由于其他处理器也可能要存取,共享内存就需要立即更新,否则不同的处理器可能用到不同的数据。共享内存是 Unix下的多进程之间的通信方法 ,这种方法通常用于一个程序的多进程间通信,实际上多个程序间也可以通过共享内存来传递信息。
2.共享内存的优缺点
- 优点:
共享内存是进程间共享数据的一种最快的方法。一个进程向共享的内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容。 - 缺点:
使用共享内存要注意的是多个进程之间对一个给定存储区访问的互斥。若一个进程正在向共享内存区写数据,则在它做完这一步操作前,别的进程不应当去读、写这些数据。
3.共享内存的模型
为了达到内存共享的目的就需要做两件事:
一是在内存划出一块区域来作为共享区;
另一件是把这个区域映 射到参与通信的各个进程空间。共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数 据传递不再涉及到内核,换句话说是进程不再通过执行进入内核的系统调用来传递彼此的数据。
内存示意图:
4.函数解析
所需的头文件:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
4.1shmget()函数
函数原型:
int shmget(key_t key, size_t size,int shmflg);
功能:创建或打开一块共享内存区。
参数;
- size:该共享存储段的长度(字节)。
- shmflg:标识函数的行为及共享内存的权限,其取值如下: IPC_CREAT:如果不存在就创建 IPC_EXCL: 如果已经存在则返回失败
- 位或权限位:共享内存位或权限位后可以设置共享内存的访问权限。
返回值:
成功:共享内存标识符。 失败:-1。
4.2shmat()函数
函数原型:
void *shmat(int shmid, const void *shmaddr, int shmflg);
功能:
将一个共享内存段映射到调用进程的数据段中。简单来理解,让进程和共享内存建立一种联系,让进程某个指针指向此共享内存。
参数:
- shmid:共享内存标识符,shmget() 的返回值。
- shmaddr:共享内存映射地址(若为 NULL 则由系统自动指定),推荐使用 NULL。
- shmflg:共享内存段的访问权限和映射条件( 通常为 0 ),具体取值如下: 0:共享内存具有可读可写权限。 SHM_RDONLY:只读。 SHM_RND:(shmaddr 非空时才有效)
- 返回值: 成功:共享内存段映射地址( 相当于这个指针就指向此共享内存 ) 失败:-1
4.3shmdt()函数
函数原型:
int shmdt(const void *shmaddr);
功能:
将共享内存和当前进程分离( 仅仅是断开联系并不删除共享内存,相当于让之前的指向此共享内存的指针,不再指向)。
参数:
shmaddr:共享内存映射地址。
返回值: 成功:0 失败:-1
4.4 shmctl()函数
函数原型:
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能:
共享内存属性的控制。
参数:
- shmid:共享内存标识符。
- cmd:函数功能的控制,其取值如下:
IPC_RMID:删除。(常用 )
IPC_SET:设置 shmid_ds 参数,相当于把共享内存原来的属性值替换为 buf 里的属性值。
IPC_STAT:保存 shmid_ds 参数,把共享内存原来的属性值备份到 buf 里。
SHM_LOCK:锁定共享内存段( 超级用户 )。
SHM_UNLOCK:解锁共享内存段。SHM_LOCK 用于锁定内存,禁止内存交换。并不代表共享内存被锁定后禁止其它进程访问。其真正的意义是:被锁定的内存不允许被交换到虚拟内存中。这样做的优势在于让共享内存一直处于内存中,从而提高程序性能。 - buf:buf是一个结构指针,它指向共享内存模式和访问权限的结构。其结构体类型定义如下:
struct shmid_ds
{
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;
}
- 返回值: 成功:0 失败:-1
5.代码示例
创建两个进程,在 write进程中创建一个共享内存,并向其写入数据,通过 read进程从共享内存中读取数据。
用vim创建shared_mem_write.c
vim shared_mem_write.c
代码:
1 #inclu