内存共享映射MMap
共享内存的本质时一段内存,可以两个进程同时访问,映射时无需读写函数
共享内存——shmap
共享内存就是物理内存中一段可以由两个或两个以上的进程共享内存的区域。
共享内存中最重要的属性是内存大小和内存地址,进程在访问共享内存前必须将共享内存映射到进程空间的一个虚拟地址中,然后任何对该虚拟地址的数据操作都将直接作用的物理内存上。多个进程对共享内存的同一区域访问时必须同步控制,即锁机制,但共享内存本身对此并不提供支持,用户进程必须自己完成相关操作,因此共享内存常与信号量共同使用,由信号量完成对共享内存区域的锁操作。
UNIX的内核采用结构shmid_ds来管理共享内存
共享内存API
- 共享内存的创建— shmget()
#include <sys/shm.h>
int shmget(key_t key, size_t size, int shmflg);
key:关键字
size:创建大小
shmfig:创建权限 0666|IPC-CREAT
返回:空间标识号
2. 共享存的映射——shmat()
#include <sys/shm.h>
void *shmat(int shmid , const void *shmaddr, int shmflg);
如shmaddr为NULL,系统将自动确定共享内存链接到进程空间首地址
注:绝大多数情况下,指定参数shmaddr为NULL,以便系统自动选择映射地址
int shmid;
char *pmat;
shmid = shmget(0x1234, 10 * 1024, 06666 | IPC_CREAT);
pmat = shmat(shmid, 0, 0);
3. 共享内存的释放——shmdt()
int shmdt(const void *shmaddr);
共享内存中有一个映射链接数,进程调用shmat成功则该值自动加1。调用shmdt并不删除该共享内存,仅删除一个链接,针对链接数减1。
4. 共享内存控制shmctl
注:共享内存一般会直接申请一个足够大的空间,但每次读写的数据量却不会很大,这势必存在共享内存数据索引的问题。UNIX内核并不像格式化磁盘一样格式化共享内存,所以用户必须人为地把大共享内存块划分为单个的小记录块
共享内存使用过程
客户端:
发送过程
访问MAP区
申请块i,要求MAP[i]=0
置MAP[i]=3
访问数据区
访问MAP区
置MAP[i]=1
接收过程
确认MAP[i]=2;
接收
MAP[i]=0;
服务器端
接收过程
访问MAP区
申请i,满足MAP[i]==1;
MAP[i]=3
处理
发送过程
访问MAP
MAP[i]=2
共享内存映射MMap
利用mmap 内存共享映射完成进程通信
可以同过文件来完成共享映射
映射方式
共享映射【MAP_SHARED】:sync 同步机制,映射空间与映射文件内同或者改动实时同步,保持一致
私有映射【MAP_PRIVATE】:将映射文件的内容拷贝给映射空间,两份数据无关
mmap() 共享映射函数
mmap(NULL,size_t size,int mod,int option , int mfd , int 0)
void * ptr = mmap() // 放回映射空间首地址
内存权限:PROT_READ | PROT_WRITE | PROT_EXEC | PROT_NONE
mfd : 映射文件的文件描述符
munmap(void * ptr , size) // 释放映射空间
mmap 使用过程
通过内存映射通过共享映射的方式修改文件 MAP_SHARED
内存共享映射 mmap munmap
- 打开文件 O_RDWR
- 获取文件大小
- 完成映射 相当于malloc 函数 用来分配空间
- 关闭文件描述符
- 可以修改内存中的数据
- 释放映射的内存