mmap拷贝文件与用常规文件IO拷贝文件效率对比

tech2023-10-01  121

  通常我们读写文件时,都是用系统提供的write和read函数,但是我们都知道文件IO函数操作文件流效率要低于mmap,因为mmap相对write/read省去将数据拷贝到用户态的操作。那么他们之间的差距有多大呢,我们来用事实说话。

1.如何快速创建一个大文件

我们做这个测试之前,需要准备一个足够大的文件来进行对比,那么在linux下,系统为我们准备了现成的方法去创建一个大文件。主要有三种方法:

1.truncate

$ truncate -s 20M filename 在命令行输入该命令就可以创建出一个20MB的文件,但是后面才发现,该文件的大小是假的,具体为什么,大家可以去研究一下,这里不做赘述。

2.fallocate

$ fallocate -l 20M filename 在命令行输入以下命令也可以创建出一个指定大小的文件,并且该大小是真实的,我们测试就是选用的这种方法。

3.dd

$ dd if=/dev/zero of=filename count=10 bs=20M 这个也是真是的大小,但是比较复杂,所以没用这个,至于这个和上面两个有什么区别,感兴趣可以自行研究一下。

2.用mmap拷贝文件

先贴上用mmap拷贝文件的方法,如果对mmap不熟悉的可以参考我上一篇总结的文章mmap ---- 内存映射原理。直接上代码:

1 #include<stdio.h> 2 #include<sys/mman.h> 3 #include<unistd.h> 4 #include<sys/types.h> 5 #include<stdlib.h> 6 #include<fcntl.h> 7 #include<sys/stat.h> 8 #include<string.h> 9 10 void mmapcopy(int sfd, size_t slen, int dfd) { 11 void *sptr = mmap(NULL, slen, PROT_READ, MAP_SHARED, sfd, 0); 12 void *dptr = mmap(NULL, slen, PROT_READ | PROT_WRITE, MAP_SHARED, dfd, 0); 13 if(dptr == MAP_FAILED) { 14 printf("mmap failed."); 15 return; 16 } 17 18 memcpy(dptr, sptr, slen); 19 20 munmap(sptr, slen); 21 munmap(dptr, slen); 22 } 23 24 int main(int argc, char* argv[]) { 25 if(argc != 3) { 26 printf("Usage: %s <src filename> <des filename>", argv[0]); 27 return -1; 28 } 29 30 int sfd; 31 int dfd; 32 33 if((sfd = open(argv[1], O_RDONLY)) < 0) { 34 printf("open src file failed."); 35 return sfd; 36 } 37 38 if((dfd = open(argv[2], O_CREAT | O_RDWR, 0664)) < 0) { 39 printf("create dst file failed."); 40 return dfd; 41 } 42 43 struct stat fst; 44 fstat(sfd, &fst); 45 truncate(argv[2], fst.st_size); 46 mmapcopy(sfd, fst.st_size, dfd); 47 48 close(sfd); 49 close(dfd); 50 51 return 0; 52 }

3.用普通文件IO拷贝文件

1 #include<stdio.h> 2 #include<unistd.h> 3 #include<sys/types.h> 4 #include<stdlib.h> 5 #include<fcntl.h> 6 7 int main(int argc, char* argv[]) { 8 if(argc != 3) { 9 printf("Usage: %s <src filename> <des filename>", argv[0]); 10 return -1; 11 } 12 13 int sfd; 14 int dfd; 15 16 if((sfd = open(argv[1], O_RDONLY)) < 0) { 17 printf("open src file failed."); 18 return sfd; 19 } 20 21 if((dfd = open(argv[2], O_CREAT | O_RDWR, 0664)) < 0) { 22 printf("create dst file failed."); 23 return dfd; 24 } 25 26 char buf[1024]; 27 int ret; 28 while(1) { 29 ret = read(sfd, buf, 1024); 30 if(ret < 0) { 31 printf("read error."); 32 break; 33 } 34 else if(ret == 0) { 35 printf("read end."); 36 break; 37 } 38 39 if(ret != write(dfd, buf, ret)) { 40 printf("write error."); 41 break; 42 } 43 44 } 45 46 close(sfd); 47 close(dfd); 48 49 return 0; 50 }

4.对比测试

  分别测试了500M,1G和2G的文件拷贝,更大的没试,按照上面的规律来看,mmap似乎都是会快一点的,理论和实际都已经证明了,mmap进行文件拷贝的时候,是比较快的,因为它毕竟省去了copy_to_usr这一次拷贝。

最新回复(0)