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

本文对比了使用mmap和普通文件IO进行大文件拷贝的效率,通过创建不同大小的文件并进行拷贝测试,实验证明mmap在文件拷贝速度上具有明显优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  通常我们读写文件时,都是用系统提供的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这一次拷贝。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值