<2006年7月>
2526272829301
2345678
9101112131415
16171819202122
23242526272829
303112345

统计

  • 随笔 - 44
  • 文章 - 0
  • 评论 - 86
  • 引用 - 0

常用链接

留言簿(6)

随笔分类(31)

随笔档案(44)

Mining

最新随笔

搜索

  •  

最新评论

阅读排行榜

评论排行榜

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 <source> <target>\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()介入。


参考:
Linux环境进程间通信(五): 共享内存(上) 对mmap的介绍很详细

posted on 2006-07-27 19:48 泡泡牛 阅读(10909) 评论(1)  编辑 收藏 引用

评论

# re: mmap使用 2007-07-11 17:35 dreamVSfight

请问mmap是linux驱动中
static struct file_operations 中定义的mmap吗?
int (*mmap) (struct file *, struct vm_area_struct *);
为什么参数不对?
dm = mmap( 0 , ( size_t )statbuf.st_size, PROT_WRITE,
MAP_SHARED, dst, 0 );
如果不是,请问一下该如何调用该函数???
  回复  更多评论    

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理