Linux下的几种文件拷贝方式效率对比

如题所述

第1个回答  2013-10-13
不管是哪种操作系统,要实现文件拷贝,必须陷入内核,从磁盘读取文件内容,然后存储到另一个文件。实现文件拷贝最通常的做法是:读取文件用系统调用read()函数,读取到一定长度的连续的用户层缓冲区,然后使用write()函数将缓冲区内容写入文件。也可以用标准库函数fread()和fwrite(),但这两个函数最终还是通过系统调用read()和write()实现拷贝的,因此可以归为一类(不过效率肯定没有直接进行系统调用的高)。一个更高级的做法是使用虚拟存储映射技术进行,这种方法将源文件以共享方式映射到虚拟存储器中,目的文件也以共享方式映射到虚拟地址空间中,然后使用memcpy高效地将源文件内容复制到目的文件中。 点击(此处)折叠或打开#include <stdio.h>#include <stdlib.h>#include <sys/mman.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <errno.h>#include <string.h>#include <sys/times.h>#define error(fmt,args...)\ printf(fmt, ##args);\ printf(":%s\n",strerror(errno))inline int cp_rw(int srcfd,int dstfd,char *buf,intlen);inline int cp_map(int srcfd,int dstfd,size_t len);int main(int argc,char **argv){ char buf[8192]; int srcfd,dstfd; clock_t start,end; struct tms stm,ntm; struct stat filestat; int tck; char cmdline[30];if(argc!=3) printf("usage: cmd <src> <dst>");tck=sysconf(_SC_CLK_TCK); start = times(&stm); if((srcfd=open(argv[1],O_RDONLY))==-1) { error("open %s error",argv[1]); exit(0); } if((dstfd=open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0666))==-1) { error("creat %s error",argv[2]); exit(0); } fstat(srcfd,&filestat); if(lseek(dstfd,filestat.st_size,SEEK_SET)==-1) { error("lseek error"); exit(0); } if(write(dstfd," ",1)!=1) { error("write error"); exit(0); } cp_map(srcfd,dstfd,filestat.st_size); close(srcfd); close(dstfd); end= times(&ntm); printf("copying %s to %s using cp_map:filesize=%lu MBytes Using %f seconds\n" ,argv[1],argv[2],filestat.st_size>>20,(end-start)/(double)tck);sprintf(cmdline,"rm -f %s",argv[2]); system(cmdline);return 0;}inline int cp_rw(int srcfd,int dstfd,char *buf,intlen){ int nread; while((nread=read(srcfd,buf,len))>0) { if(write(dstfd,buf,nread)!=nread) { error("write error"); return -1; } } if(nread ==-1) { error("read error"); return -1; } return 0;}inline int cp_map(int srcfd,int dstfd,size_t len){ char *src,*dst; if((src=mmap(0,len,PROT_READ,MAP_SHARED,srcfd,0))==MAP_FAILED) { error("mmap src error"); return -1; } if((dst=mmap(0,len,PROT_WRITE,MAP_SHARED,dstfd,0))==MAP_FAILED) { error("mmap dst error"); return -1; } if(memcpy(dst,src,len)==NULL) { error("memcpy error"); return -1; } munmap(src,len); munmap(dst,len); return 0;}运行,拷贝一个1.1G的文件,得到如下结果[root@garden copy]# ./copy /home/ker.tgz ./ker.tgzcopying /home/ker.tgz to ./ker.tgz using cp_map:filesize=1030 MBytes Using 61.900000 secondscopying /home/ker.tgz to ./ker.tgz using cp_rw:filesize=1030 MBytes Using 34.330000 seconds使用read/write的方法居然比mmap的快一倍,这是怎么回事呢?理论上mmap系统调用只进行了一次,而且拷贝文件是直接在内核空间进行的,read/write则需要通过系统调用把内核空间的缓存复制到用户空间,再将用户空间缓存复制到内核空间,拷贝次数明显多了一个呢?速度为什么于理论预测的不一致呢?本回答被提问者采纳
相似回答