Linux内存映射

使用内存映射处理大文件很方便,在Windows系统中,实现了这样的借口。在Linux中我们也可以通过mmap函数来实现。以下内容完全参考自
http://blog.chinaunix.net/u2/76292/showart_1892637.html
如有冒犯,请谅解

mmap函数实现把一个文件映射到一个内存区域,从而我们可以像读写内存一样读写文件,他比单纯调用read/write也要快上许多。在某些时候我们可以把内存的内容拷贝到一个文件中实现内存备份,当然,也可以把文件的内容映射到内存来恢复某些服务。另外,mmap实现共享内存也是其主要应用之一,mmap系统调用使得进程之间通过映射同一个普通文件实现共享内存。
关于mmap的内容请看《Unix环境高级编程》12章。在这里,说一下使用mmap函数时可能遇到的问题:

  //下面的代码把文件1.ls中的内容通过mmap函数写入2.ls中,忽略出错处理

        int fd=open("1.ls",O_RDONLY);
        int fd2=open("2.ls",O_CREAT|O_RDWR|O_TRUNC,S_IRUSR|S_IWUSR);//必须设置读写权限,若只有写权限,会产生SIGSEGV信号
                                                                //mmap进行文件映射时必须先读取文件`

        struct stat st;
        fstat(fd,&st);
        lseek(fd2,st.st_size-1,SEEK_SET);
        write(fd2,"",1);        //必须的,如果不设置,当写入数据的时候会遇到文件结束符,产生SIGBUS信号
        void *_src=mmap(NULL,st.st_size,PROT_READ,MAP_SHARED, fd,0);
        void *_des=mmap(NULL,st.st_size,PROT_WRITE,MAP_SHARED,fd2,0);

        close(fd);      //关闭文件后 依然可修改文件内容
        close(fd2);
        memcpy(_des,_src,st.st_size);

总结一下,可能产生的问题如下:
    1.进行文件映射的描述符必须拥有读权限,否则会产生SIGSEGV信号
    2.把内存内容写入映射文件时,必须确保被写文件当前位置到文件结尾的长度不小于所写内容长度,否则产生SIGBUS信号
    3.关闭文件描述符并不能保证文件内容不被修改
    4.munmap并不能使映射的内容写回磁盘
也许会奇怪为什么有总线错误,其实我也郁闷了好久,才弄明白.lseek了一个空洞 但是并引起i/o操作
也就是说如果lseek之后没有发生i/o操作时,lseek只是把偏移量给改了一下并没有在磁盘上分配存储区
而你的文件是新建的 存储的空间长度为0 lseek之后还是为0.把mmap到系统的线性地址空间,然后进行复制的话就会出错.
   一种方法如上,lseek后加个write。还有一个办法就是ftruncate(fdout, statbuf.st_size) == 0了

#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 argc,char *argv[]) 
{ 
int fdin,fdout; 
void *src,*dst; 
size_t pagesize; 
struct stat statbuf; 
if(argc != 3) 
{ 
printf("usage : %s <fromfile> <tofile>/n",argv[0]); 
return 1; 
} 
    pagesize = sysconf(_SC_PAGESIZE); 
printf("PageSize: %ld/n", (long)pagesize); 
if((fdin = open(argv[1],O_RDONLY)) == -1) 
{ 
printf("can't open file %s/n",argv[1]); 
return 1; 
} 
if((fdout = open(argv[2],O_RDWR | O_CREAT | O_TRUNC,0644)) == -1) 
{ 
printf("can't create file %s/n",argv[2]); 
return 1; 
} 
assert(fstat(fdin,&statbuf) == 0); 
printf("filein size = %ld/n",statbuf.st_size); 
assert(ftruncate(fdout, statbuf.st_size) == 0 
&& fstat(fdout, &statbuf) == 0); 
printf("fileout size = %ld/n",statbuf.st_size); 
    src = mmap(0,statbuf.st_size,PROT_READ,MAP_SHARED,fdin,0); 
if( src == MAP_FAILED ) 
{ 
printf("mmap error for fdin./n"); 
return 1; 
} 
    dst = mmap(0,statbuf.st_size,PROT_READ | PROT_WRITE,MAP_SHARED,fdout,0); 
if( dst == MAP_FAILED ) 
{ 
printf("mmap error for fdout./n"); 
return 1; 
} 
memcpy(dst,src,statbuf.st_size); 
close(fdin); 
close(fdout); 
return 0; 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值