mmap内存映射复习
c语言初学时,比较常见的一个习题就是实现cp。
使用c库实现的cp就不赘述了。
最近工作用到内存映射,就拿来练下手,复习一下mmap的用法。
很简单,将目标文件和源文件映射到内存,然后使用memcpy拷贝即可。
可以省去中间缓存的创建,代码页较为简单,拷贝速度也不错。
1 #include <stdio.h> 2 #include <string.h> 3 #include <sys/types.h> 4 #include <sys/stat.h> 5 #include <unistd.h> 6 #include <fcntl.h> 7 #include <sys/mman.h> 8 9 #define COFYMODE 0666 10 11 int copy(const char* src, const char* dest) 12 { 13 int ret = -1; 14 int in_fd = -1, out_fd = -1; 15 size_t filesize; 16 char nullbyte; 17 void *source_addr = NULL; 18 void *dest_addr = NULL; 19 20 /* check args */ 21 if(src == NULL || dest == NULL){ 22 fprintf(stderr,"file path can not be null\n"); 23 return ret; 24 } 25 26 /* open files */ 27 if((in_fd=open(src, O_RDONLY))==-1) { 28 fprintf(stderr, "Cannot open %s\n", src); 29 return ret; 30 } 31 32 33 #if defined(i386) || defined(__x86_64) || defined(__x86_64__) || defined(i686) 34 if((out_fd=open(dest, O_RDWR|O_CREAT|O_TRUNC,COFYMODE))==-1) 35 { 36 fprintf(stderr, "Cannot open %s\n", dest); 37 ret = -1; 38 goto cleanup; 39 } 40 #else 41 if((out_fd=open(dest, O_WRONLY|O_CREAT|O_TRUNC,COFYMODE))==-1) 42 { 43 fprintf(stderr, "Cannot create %s\n", dest); 44 ret = -1; 45 goto cleanup; 46 } 47 #endif 48 49 if((filesize=lseek(in_fd,0,SEEK_END))==-1) 50 { 51 fprintf(stderr, "Could not seek to end of file %s\n", src); 52 ret = -1; 53 goto cleanup; 54 } 55 56 if(filesize == 0) 57 { 58 ret = 0; 59 goto cleanup; 60 } 61 62 lseek(out_fd,filesize-1,SEEK_SET); 63 write(out_fd,&nullbyte,1); 64 65 /* setup the memory maps */ 66 if((source_addr=mmap(NULL,filesize,PROT_READ,MAP_SHARED,in_fd,0))==(void *)-1) 67 { 68 fprintf(stderr, "Error mapping file %s\n", src); 69 ret = -1; 70 goto cleanup; 71 } 72 73 74 if((dest_addr=mmap(NULL,filesize,PROT_WRITE,MAP_SHARED,out_fd,0))==(void *)-1) 75 { 76 fprintf(stderr, "Error mapping file %s\n", dest); 77 ret = -1; 78 goto cleanup; 79 } 80 81 /* copy the input to output by doing a memcpy */ 82 memcpy(dest_addr,source_addr,filesize); 83 84 cleanup: 85 /*unmap the fiels */ 86 if(source_addr) munmap(source_addr,filesize); 87 if(dest_addr) munmap(dest_addr,filesize); 88 89 /* close the files */ 90 if(in_fd > 0)close(in_fd); 91 if(out_fd > 0) close(out_fd); 92 93 return ret; 94 } 95 96 int main(int argc, char* argv[]) 97 { 98 if(argc < 3) 99 { 100 fprintf(stderr, "useage: %s src_file dest_file", argv[0]); 101 return -1; 102 } 103 104 return copy(argv[1], argv[2]); 105 }