利用mmap实现的一个文件拷贝例子

利用mmap实现的一个文件拷贝例子

/* 
 * gcc -Wall -O3 -o copy_mmap copy_mmap.c
 
  */ 
#include 
  <  stdio.h  > 
#include 
  <  stdlib.h  > 
#include 
  <  string  .h  >      /*   for memcpy   */ 
#include 
  <  strings.h  > 
#include 
  <  sys  /  mman.h  > 
#include 
  <  sys  /  types.h  > 
#include 
  <  sys  /  stat.h  > 
#include 
  <  fcntl.h  > 
#include 
  <  unistd.h  > 

#define   PERMS 0600 

int   main (   int   argc,   char     *   argv[] )
{
    
  int            src, dst;
    
  void            *  sm,   *  dm; 
    
  struct   stat  statbuf;

    
  if   ( argc   !=     3   )
    {
        fprintf( stderr, 
  "   Usage: %s  \n  "  , argv[  0  ] );
        exit( EXIT_FAILURE );
    }
    
  if   ( ( src   =   open( argv[  1  ], O_RDONLY ) )   <     0   )
    {
        perror( 
  "  open source  "   );
        exit( EXIT_FAILURE );
    }
    
  /*   为了完成复制,必须包含读打开,否则mmap()失败   */ 
    
  if   ( ( dst   =   open( argv[  2  ], O_RDWR   |   O_CREAT   |   O_TRUNC, PERMS ) )   <     0   )
    {
        perror( 
  "  open target  "   );
        exit( EXIT_FAILURE );
    }
    
  if   ( fstat( src,   &  statbuf )   <     0   )
    {
        perror( 
  "  fstat source  "   );
        exit( EXIT_FAILURE );
    }
    
  /* 
     * 参看前面man手册中的说明,mmap()不能用于扩展文件长度。所以这里必须事
     * 先扩大目标文件长度,准备一个空架子等待复制。
     
  */ 
    
  if   ( lseek( dst, statbuf.st_size   -     1  , SEEK_SET )   <     0   )
    {
        perror( 
  "  lseek target  "   );
        exit( EXIT_FAILURE ); 
    } 
    
  if   ( write( dst,   &  statbuf,   1   )   !=     1   )
    {
        perror( 
  "  write target  "   );
        exit( EXIT_FAILURE );
    } 
    
    
  /*   读的时候指定 MAP_PRIVATE 即可   */ 
    sm 
  =   mmap(   0  , ( size_t )statbuf.st_size, PROT_READ,
               MAP_PRIVATE 
  |   MAP_NORESERVE, src,   0   );
    
  if   ( MAP_FAILED   ==   sm )
    {
        perror( 
  "  mmap source  "   );
        exit( EXIT_FAILURE );
    }
    
  /*   这里必须指定 MAP_SHARED 才可能真正改变静态文件   */ 
    dm 
  =   mmap(   0  , ( size_t )statbuf.st_size, PROT_WRITE,
               MAP_SHARED, dst, 
  0   );
    
  if   ( MAP_FAILED   ==   dm )
    {
        perror( 
  "  mmap target  "   );
        exit( EXIT_FAILURE );
    }
    memcpy( dm, sm, ( size_t )statbuf.st_size );
    
  /* 
     * 可以不要这行代码
     *
     * msync( dm, ( size_t )statbuf.st_size, MS_SYNC );
     
  */ 
    
  return  ( EXIT_SUCCESS );

mmap()好处是处理大文件时速度明显快于标准文件I/O,无论读写,都少了一次用户空间与内核空间之间的复制过程。操作内存还便于设计、优化算法。

文件I/O操作/proc/self/mem不存在页边界对齐的问题,但至少Linux的mmap()的最后一个形参offset并未强制要求页边界对齐,如果提供的值未对齐,系统自动向上舍入到页边界上。malloc()分配得到的地址不见得对齐在页边界上。
        
/proc/self/mem和/dev/kmem不同。root用户打开/dev/kmem就可以在用户空间访问到内核空间的数据,包括偏移0处的数据,系统提供了这样的支持。显然代码段经过/proc/self/mem可写映射后已经可写,无须mprotect()介入。



from:http://blog.chinaunix.net/uid-20662363-id-1904142.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值