内存映射
将磁盘文件中的数据映射到内存,用户通过修改内存就能修改磁盘文件
相关的系统调用:
void *mmap()
功能:将一个文件或设备的数据映射到内存中
参数:
- void *addr : NULL 由内核指定
- length : 要映射的数据长度,这个值不能为0,建议使用文件的长度。获取文件的长度,stat,lseek
- port : 对申请映射区的操作权限
- PORT_EXEC : 可执行的权限
- PORT_READ : 读权限
- PORT_NONE :没有权限
- 要操作映射区必须要有读权限
- flags :
- MAP_SHARED : 映射区的数据会自动和磁盘文件进行同步,进程间通信必须要设置这个选项
- MAP_PRIVATE : 不同步,内存映射区的数据改变了对原来的文件不会进行修改,会重新创建一个新的文件
- fd :需要映射的文件的文件描述符
- 通过open得到,open的是一个磁盘文件
- 注意:文件的大小不能为0,open指定的权限不能和port参数有冲突
- open:只读/读写 port:PORT_READ
- open:读写 port : PORT_READ | PORT_WRITE
- offset : 偏移量,一般不用
- 返回值:返回创建的内存的首地址,失败返回MAP_FAILED,
int munmap()
- 功能:释放内存
- 参数:
- addr :要释放的内存首地址
- length :释放的内存大小
使用内存映射实现进程间通信:
- 有关系的·进程(父子进程)
- 通过唯一父进程,创建内存映射区
- 然后创建子进程
- 父子进程共享创建的内存映射区
- 没有关系的进程间通信:
- 准备一个大小不是0的磁盘文件
- 进程1:通过磁盘文件创建内存映射区,得到一个操作这块内存的指针
- 进程2:通过磁盘文件创建内存映射区,得到一个操作这块内存的指针
- 使用内存映射区进行通信
注意:内存映射区通信,是非阻塞的。
实现
父进程读取到子进程输入的数据
/*
#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
int munmap(void *addr, size_t length);
*/
#include<stdio.h>
#include<sys/mman.h>
#include<fcntl.h>
#include<sys/types.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<wait.h>
int main(){
//打开一个文件
int fd = open("test.txt",O_RDWR);
//获取文件的大小
int size = lseek(fd,0,SEEK_END);
//创建内容映射区
void *ptr = mmap(NULL,size,PROT_READ | PROT_WRITE, MAP_SHARED, fd , 0);
// 返回一个指针
if(ptr == MAP_FAILED){
perror("mmap");
exit(0);
}
//创建子进程
pid_t pid = fork();
if (pid > 0)
{
wait(NULL);
//父进程
char buf[64];
strcpy(buf,(char *)ptr);
printf("read data : %s\n",buf);
}
else if(pid == 0)
{
//子进程
strcpy((char *)ptr,"nihao!!!!");
}
//关闭内存映射区
munmap(ptr,size);
return 0;
}
文件也发生了改变