1.mmap函数介绍
void *mmap(void *addr,size_t length,int prot,int flags,int fd,off_t offset);
返回:成功:返回创建的映射区首地址;失败:MAP_FAILED 宏
参数:
addr: 建设映射区的首地址,由Linux内核指定,使用时,直接传递NULL
length:欲创建映射区的大小
prot:映射区权限 PROT_READ、PROT_WRITE、PROT_READ | PROT_WAITE (读写)
flags: 标志位参数 (常用于设定更新物理区域、设置共享、创建匿名映射区)
MAP_SHARED: 会将映射区所做的操作反映到物理设备(磁盘)上
MAP_PRIVATE: 映射区所做的修改不会反映到物理设备
fd: 用来建立映射区的文件描述符
offset: 映射文件的偏移(4k 的整数倍) (映射一部分)
2.mmap实践
1.打开一个文件(或者穿件一个新文件),
2.用mmap函数,创建内存映射区(参数MAP_SHARED,会反映到映射区)
3.通过指针p,向内存映射区写入数据
4.关闭映射区,关闭文件
#include<stdio.h>
#include<fcntl.h>
#include<unistd.h>
#include<string.h>
#include<stdlib.h>
#include<sys/mman.h>
int main()
{
int len, ret;
char *p = NULL;
int fd = open("mytest.txt",O_CREAT|O_RDWR,0644);//打开文件
if(fd < 0){
perror("open error:");
exit(1);
}
len = ftruncate(fd,4);
if( len == -1 ){
perror("ftruncate error:");
exit(1);
}
//泛型指针可以和任意的指针类型,完成隐式转换
p = mmap(NULL, 4, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);//创建映射区
if (p == MAP_FAILED){
perror("mmap error:");
exit(1);
}
strcpy(p , "abc"); //模拟p指针向内存写数据
ret = munmap(p, 4);
if(ret == -1){
perror("munmap error:");
exit(1);
}
close(fd);//关闭文件
return 0;
}
5.结果,是mytest.txt文件中,有写入的数据 “abc”
3.mmap相关问题
0.可以open的时候 O_CREAT一个新文件来创建映射区吗?
可以,上面的代码就是以 O_CREAT 一个新文件来创建映射区的。
1.可不可以创建大小为0的映射区呢?不可以
2.如果p++ ,munmap可否成功?
不能成功,因为munmap 回收时,要传入映射区的首地址
3.如果open时O_RDONLY,mmap时PROT参数指定PROT_READ | PROT_WRITE 会怎样?
不行,权限不够,映射区无写权限。
若mmap函数flags参数修改为 MAP_PRIVATE,会出现总线错误,由于硬件异常导致的,和实际空间大小和访问权限有关。
若mmap函数flags参数修改为 MAP_SHARED,以只写方式打开文件,以只写方式创建映射区。
若都修改为只读
结论:1.创建映射区的权限,小于等于文件打开的权限
2.创建映射区的过程,隐含着对文件的读操作
3.如果文件偏移量为1000会怎样?
不行,必须是4k的整数倍(一页的大小)。映射区是MMU帮助完成映射,所以为4k的倍数