一.为什么需要使用共享内存?
1.导语
共享内存是最高效的进程之间的通信,因为它不涉及到进程之间的任何传输,是系统出于多个进程之间通讯的考虑,预留的一块内存区域.
它在内核态和用户态之间交互了两次,一次是从输入文件到共享内存区域,另一次是从共享内存区域写出到输出文件之中。
进程在使用共享内存的时候,只有当通信完毕之后,才能继续保持,直到通信结束之后。是最快的IPC之一,不涉及进程之间的任何数据传输,所以我们必须用其他辅助手段来同步进程对于共享内存的访问
2.共享内存的内存模型
共享内存允许两个或更多进程访问同一块内存,就如同 malloc() 函数向不同进程返回了指向同一个物理内存区域的指针。当一个进程改变了这块地址中的内容的时候,其它进程都会察觉到这个更改。共享存储的一种形式,多个进程可以将同一个文件映射到一个地方
但是由于系统内核没有提供共享内存的同步方式,必须自己解决这类问题,以自己的同步措施来进行解决,不然一个进程和另外一个进程同时进行读写的话,会出现问题。
当一个进程想和另外一个进程通信的时候,它将按以下顺序运行:
获取mutex对象,锁定共享区域。
将要通信的数据写入共享区域。
释放mutex对象。
要使用一块共享内存
进程必须首先分配它
随后需要访问这个共享内存块的每一个进程都必须将这个共享内存绑定到自己的地址空间中
当完成通信之后,所有进程都将脱离共享内存,并且由一个进程释放该共享内存块
三.共享内存中的System V
- 使用System V 共享内存和共享文件映射, System V共享内存模型使用的是键和标识符,使用一个共享内存映射IPC要求创建一个磁盘文件,无需对于共享区域进行持续存储也需要这样做
一.System V
- 当我们创建了一块共享内存的时候,其实就是在tmpfs文件系统中也就是/dev/shm下的创建了一个文件,意味着创建了一个iNode 节点
-系列API的使用
#include <sys/shm.h>
#include <sys/types.h> key_t ftok ( const char* fname, int fd);成功返回一个key_t值, 失败返回-1
注意, 当文件路径和子序号都相同时返回的并不一定永远返回一样的key值, 如果该路径指向的文件或者目录被删除而又重新创建, 就算名字还是一样, 但是文件系统会赋予它不同的 iNode 信息, 所以返回的 key 值就不同了
- shmget
#include <sys/shm.h> int shmget (key_t key, size_t size, int shmflag);
用来创建一块共享内存并返回其 id 或者获得一块已经被创建的共享内存的 id
- key_t key 参数用来唯一标识一段全局共享内存, 通常通过 ftok 函-数获得,
- size_t size 参数是创建的共享内存的大小, 单位为字节, 如果是要创建一块共享内存, 此参数必须被指定, 如果是要获取一块创建好的共享内存的 id, 可以将其设置为 0
- int shmgflg 参数为 0 为获取共享内存 id, 为 IPC_CREAT 时是创建一个新的共享内存, 通常要同时指定权限 (和权限进行 | 运算)