将文件映射到内存
mmap的好处:
- 和read、write系统调用相比不会产生无关的副本;
- 如果不出错就不会有系统调用、操作环境切换等开销;
- 不再需要lseek调用。
mmap的坏处:
- 内存映射总是PAGESIZE的整数倍,会浪费一定的内存;
- 如果要映射的内容非常大的时候可能找不到连续的线性地址空间;
- 创建并维护内核相关数据结构,这部分可能抵消双重副本节省下的开销,尤其是大型频繁访问的文件。
下面是一个文件映射比较全面的例子:
int main(){
//取得页大小
//int pagesize = sysconf(_SC_PAGESIZE);
int pagesize = getpagesize();
printf("系统的页大小为 :%d\n", pagesize);
int i, len ,fd = open("test", O_RDWR);
char * p;
//通过mmap映射文件
p = (char*)mmap(0, 10, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if(p == MAP_FAILED){
printf("映射文件失败\n");
return 1;
}else{
printf("映射文件成功,文件内容是 :%s\n", p);
printf("映射开始的位置 :%u\n", (unsigned int)p);
printf("开始位置对PAGE_SIZE的余数:%d\n", ((int)p)%pagesize);
len=strlen(p);
//把test中的字符都变成'a'
for(i = 0; i < len; i++){
*(p+i) = 'a';
}
//调整映射的大小,MREMAP_MAYMOVE说明是可移动的
p = (char*)mremap(p, 10, 20, MREMAP_MAYMOVE);
if(p == MAP_FAILED){
printf("改变映射大小失败!\n");
}else{
printf("改变映射大小成功!\n");
}
//修改内存访问权限
i = mprotect(p, 20, PROT_READ);
if(p == MAP_FAILED){
printf("变更访问权限失败!\n");
}else{
printf("变更访问权限成功!\n");
}
//*p='b';这是会引起段错误
//给内核提建议(预读)
i = madvise(p, 20, MADV_WILLNEED);
if(i == -1){
printf("建议失败!\n");
}else{
printf("建议成功!\n");
}
//解除映射
i = munmap(p, 10);
if(i == -1){
printf("解除映射失败!\n");
}else{
printf("解除映射成功!\n");
}
}
close(fd);
return 0;
}