mmap is used to realize file copy function

  • 2020-06-19 11:15:20
  • OfStack

mmap implementation of 1 file copy example, for your reference, the specific content is as follows


/* 
 * 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 );
 }
  /*  In order to complete the copy, you must include a read open, otherwise mmap() failure  */ 
  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 );
 }
  /* 
  *  See the front man The instructions in the manual, mmap() Cannot be used to extend file length. So something has to be done here 
  *  First, expand the target file length and prepare 1 An empty shelf waiting to be copied. 
  */ 
  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 );
 } 
 
  /*  Specify when reading  MAP_PRIVATE  Can be  */ 
 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 );
 }
  /*  You have to specify  MAP_SHARED  It's possible to really change static files  */ 
 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 );
  /* 
  *  You can do without this line of code 
  *
  * msync( dm, ( size_t )statbuf.st_size, MS_SYNC );
  */ 
  return ( EXIT_SUCCESS );
}

The benefit of mmap() is that it handles large files much faster than the standard I/O files, with one less copy between user space and kernel space, either read or write. Operating memory also facilitates the design and optimization of algorithms.

The file I/O operation /proc/self/mem does not have a page boundary alignment problem, but at least offset, the last parameter of mmap() of Linux, does not require page boundary alignment. If the supplied value is not aligned, the system will automatically round up to the page boundary. malloc() assigns addresses that do not necessarily line up at page boundaries.

/proc/self/mem is different from /dev/kmem. root users who open /dev/kmem can access kernel space data in user space, including data at offset 0, which is supported by the system. It is clear that the code segment is writable after a /proc/self/mem writable map without mprotect() intervention.


Related articles: