Linux下是否有文件拷贝的库函数
2个回答
展开全部
不管是哪种操作系统,要实现文件拷贝,必须陷入内核,从磁盘读取文件内容,然后存储到另一个文件。实现文件拷贝最通常的做法是:读取文件用系统调用read()函数,读取到一定长度的连续的用户层缓冲区,然后使用write()函数将缓冲区内容写入文件。也可以用标准库函数fread()和fwrite(),但这两个函数最终还是通过系统调用read()和write()实现拷贝的,因此可以归为一类(不过效率肯定没有直接进行系统调用的高)。一个更高级的做法是使用虚拟存储映射技术进行,这种方法将源文件以共享方式映射到虚拟存储器中,目的文件也以共享方式映射到虚拟地址空间中,然后使用memcpy高效地将源文件内容复制到目的文件中。点击(此处)折叠或打开#include#include#include#include#include#include#include#include#include#include#defineerror(fmt,args)\printf(fmt,##args);\printf(":%s\n",strerror(errno))inlineintcp_rw(intsrcfd,intdstfd,char*buf,intlen);inlineintcp_map(intsrcfd,intdstfd,size_tlen);intmain(intargc,char**argv){charbuf[8192];intsrcfd,dstfd;clock_tstart,end;structtmsstm,ntm;structstatfilestat;inttck;charcmdline[30];if(argc!=3)printf("usage:cmd");tck=sysconf(_SC_CLK_TCK);start=times(&stm);if((srcfd=open(argv[1],O_RDONLY))==-1){error("open%serror",argv[1]);exit(0);}if((dstfd=open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0666))==-1){error("creat%serror",argv[2]);exit(0);}fstat(srcfd,&filestat);if(lseek(dstfd,filestat.st_size,SEEK_SET)==-1){error("lseekerror");exit(0);}if(write(dstfd,"",1)!=1){error("writeerror");exit(0);}cp_map(srcfd,dstfd,filestat.st_size);close(srcfd);close(dstfd);end=times(&ntm);printf("copying%sto%susingcp_map:filesize=%luMBytesUsing%fseconds\n",argv[1],argv[2],filestat.st_size>>20,(end-start)/(double)tck);sprintf(cmdline,"rm-f%s",argv[2]);system(cmdline);return0;}inlineintcp_rw(intsrcfd,intdstfd,char*buf,intlen){intnread;while((nread=read(srcfd,buf,len))>0){if(write(dstfd,buf,nread)!=nread){error("writeerror");return-1;}}if(nread==-1){error("readerror");return-1;}return0;}inlineintcp_map(intsrcfd,intdstfd,size_tlen){char*src,*dst;if((src=mmap(0,len,PROT_READ,MAP_SHARED,srcfd,0))==MAP_FAILED){error("mmapsrcerror");return-1;}if((dst=mmap(0,len,PROT_WRITE,MAP_SHARED,dstfd,0))==MAP_FAILED){error("mmapdsterror");return-1;}if(memcpy(dst,src,len)==NULL){error("memcpyerror");return-1;}munmap(src,len);munmap(dst,len);return0;}运行,拷贝一个1.1G的文件,得到如下结果[root@gardencopy]#./copy/home/ker.tgz./ker.tgzcopying/home/ker.tgzto./ker.tgzusingcp_map:filesize=1030MBytesUsing61.900000secondscopying/home/ker.tgzto./ker.tgzusingcp_rw:filesize=1030MBytesUsing34.330000seconds使用read/write的方法居然比mmap的快一倍,这是怎么回事呢?理论上mmap系统调用只进行了一次,而且拷贝文件是直接在内核空间进行的,read/write则需要通过系统调用把内核空间的缓存复制到用户空间,再将用户空间缓存复制到内核空间,拷贝次数明显多了一个呢?速度为什么于理论预测的不一致呢?
展开全部
1 /*
2 * Copy a (real) file to another (real) file.
3 * file can be a regular file or a simlink
4 */
5 int create_copy_file(const char *source, const char *target)
6 {
7 struct stat src_stat;
8
9 if (lstat(source, &src_stat) == -1)
10 return -1;
11
12 if (S_ISLNK(src_stat.st_mode)) {
13 char lnk[1024];
14 int lnk_size;
15 if ((lnk_size = readlink(source, lnk, 1023)) == -1)
16 return -2;
17 lnk[lnk_size] = '\0';
18 if (symlink(lnk, target) == -1)
19 return -3;
20 } else if (S_ISREG(src_stat.st_mode)) {
21 int src, dst;
22 int rsize;
23 char buf[1024];
24 if ((src = open(source, O_RDONLY)) == -1) {
25 close(dst);
26 return -4;
27 }
28 if ((dst = creat(target, src_stat.st_mode)) == -1)
29 return -5;
30 while ((rsize = read(src, buf, 1024))) {
31 if (rsize == -1 && errno == EINTR)
32 continue ;
33 if (rsize == -1) {
34 close(src);
35 close(dst);
36 return -6;
37 }
38 while (write(dst, buf, rsize) == -1)
39 if (errno != EINTR) {
40 close(src);
41 close(dst);
42 return -7;
43 }
44 }
45 close(src);
46 close(dst);
47 } else {
48 return -8;
49 }
50 return 0;
51 }
2 * Copy a (real) file to another (real) file.
3 * file can be a regular file or a simlink
4 */
5 int create_copy_file(const char *source, const char *target)
6 {
7 struct stat src_stat;
8
9 if (lstat(source, &src_stat) == -1)
10 return -1;
11
12 if (S_ISLNK(src_stat.st_mode)) {
13 char lnk[1024];
14 int lnk_size;
15 if ((lnk_size = readlink(source, lnk, 1023)) == -1)
16 return -2;
17 lnk[lnk_size] = '\0';
18 if (symlink(lnk, target) == -1)
19 return -3;
20 } else if (S_ISREG(src_stat.st_mode)) {
21 int src, dst;
22 int rsize;
23 char buf[1024];
24 if ((src = open(source, O_RDONLY)) == -1) {
25 close(dst);
26 return -4;
27 }
28 if ((dst = creat(target, src_stat.st_mode)) == -1)
29 return -5;
30 while ((rsize = read(src, buf, 1024))) {
31 if (rsize == -1 && errno == EINTR)
32 continue ;
33 if (rsize == -1) {
34 close(src);
35 close(dst);
36 return -6;
37 }
38 while (write(dst, buf, rsize) == -1)
39 if (errno != EINTR) {
40 close(src);
41 close(dst);
42 return -7;
43 }
44 }
45 close(src);
46 close(dst);
47 } else {
48 return -8;
49 }
50 return 0;
51 }
本回答被网友采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询