Linux mmap的学习
本来以前mmap是很简单的,看下参数用法就ok,结果遇到了一大堆麻烦,google了很多博客,都写得很浅显,就介绍一下参数然后再给了一个简单得不得了的代码,就完了,所以纠结了我差不多一天时间。
mmap怎么用我就不说了,网上很多,在这里就把我犯的错误经验分享出来,先贴一下我用mmap实现拷贝任意文件的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
int main()
{
int fdin,fdout, len = 0, pages = 0, offset = 0, lastPage = 0;
char *src, *dst;
size_t pagesize;
struct stat statbuf;
if((fdin = open("mmmap.c", O_RDWR)) == -1)
{
printf("can't open fdin ");
return 1;
}
if((fdout = open("mmmmap1.c",O_RDWR | O_CREAT | O_TRUNC,0644)) == -1)
{
if(EEXIST == errno)
{
fd = open("mmmmap1.c", O_RDWR);
if(-1 == fd)
{
perror("open");
exit(-1);
}
}
else
{
perror("open");
exit(-1);
}
}
//lseek(fd, 4096, SEEK_SET);
//write(fd, " ", 1);
pagesize = sysconf(_SC_PAGESIZE);
printf("pagesize = %ld\n", pagesize);
assert(fstat(fdin,&statbuf) == 0);
printf("statbuf.st_size = %d\n", statbuf.st_size);
pages = statbuf.st_size/pagesize;
if((statbuf.st_size)%pagesize != 0)
{
lastPage = (statbuf.st_size)%pagesize;
pages += 1;
printf("lastPage = %d\n", lastPage);
}
printf("pages = %d\n", pages);
//assert(ftruncate(fdout, statbuf.st_size) == 0);
if (lastPage != 0)
{
len += lastPage;
}
else
{
len += pagesize;
}
while(pages--)
{
assert(ftruncate(fdout, len) == 0);
src = (char *)mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fdin, offset);
if( src == MAP_FAILED )
{
printf("mmap error for fdin.\n");
return 1;
}
dst = mmap(0,pagesize,PROT_READ | PROT_WRITE,MAP_SHARED,fdout,offset);
if( dst == MAP_FAILED )
{
printf("mmap error for fdout.\n");
return 1;
}
memcpy(dst,src, pagesize);
offset += pagesize;
if (pages == 1 && lastPage != 0)
{
len += lastPage;
}
else
{
len += pagesize;
}
munmap(src, pagesize);
munmap(dst, pagesize);
}
close(fdin);
close(fdout);
return 0;
}
我遇到的问题:
1.报段错误,打开的读写方式和mmap里的参数不一致会报此错
2.bus error,文件为空,或者mmap了一页而你却要去操作第二页
3.新建的写入文件有时会打开异常,那是因为在mmap的时候往文件里写了不应该写入的字符,所以建议更新文件大小的时候不要用write,用ftruncate
反正记住mmap是一页一页映射的,len和offset参数要是页的倍数就行了...
有什么问题欢迎留言讨论..…^_^