欢迎来到入门教程网!

C语言

当前位置:主页 > 软件编程 > C语言 >

利用mmap实现文件拷贝功能

来源:本站原创|时间:2020-01-10|栏目:C语言|点击:

利用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()介入。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

上一篇:C++实现大整数乘法(字符串乘法)

栏    目:C语言

下一篇:C++实现简单射击小游戏

本文标题:利用mmap实现文件拷贝功能

本文地址:https://www.xiuzhanwang.com/a1/Cyuyan/182.html

网页制作CMS教程网络编程软件编程脚本语言数据库服务器

如果侵犯了您的权利,请与我们联系,我们将在24小时内进行处理、任何非本站因素导致的法律后果,本站均不负任何责任。

联系QQ:835971066 | 邮箱:835971066#qq.com(#换成@)

Copyright © 2002-2020 脚本教程网 版权所有