mmap拷贝文件
来源:互联网 发布:中国科技大学人工智能 编辑:程序博客网 时间:2024/05/16 06:26
#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <sys/mman.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <sys/time.h>#include <string.h>#define BUFFER_SIZE 1void my_copy1(){ int fin,fout; //文件描述符 void *start; void *end; struct stat sb; if((fin = open("file.in",O_RDONLY)) < 0){ perror("open error"); exit(EXIT_FAILURE); } if((fout = open( "file.out",O_RDWR | O_CREAT | O_TRUNC,00600)) < 0 ){ perror( "write error" ); exit( EXIT_FAILURE ); } fstat(fin,&sb); //这块必须给fout一个需求大小的偏移,因为mmap没有扩展空间的能力 if(lseek(fout,sb.st_size-1,SEEK_SET) < 0 ){ exit(EXIT_FAILURE); } if(write(fout, &sb,1) != 1 ){ exit(EXIT_FAILURE); } start = mmap(NULL,sb.st_size,PROT_READ,MAP_PRIVATE,fin,0); if(start == MAP_FAILED) return; end = mmap(0,(size_t)sb.st_size,PROT_WRITE,MAP_SHARED,fout,0); if(end == MAP_FAILED){ return ; } memcpy(end,start,(size_t)sb.st_size); munmap(start,sb.st_size); //关闭映射 munmap(end,sb.st_size); close(fin); close(fout); return;}void my_copy2(){ int fin,fout; int bytes_read,bytes_write; char buffer[BUFFER_SIZE]; char *ptr; if((fin = open("file.in",O_RDONLY)) < 0){ perror("open error"); exit(EXIT_FAILURE); } if((fout = open( "file.out",O_RDWR | O_CREAT | O_TRUNC,00700)) < 0 ){ perror( "write error" ); exit( EXIT_FAILURE ); } while(bytes_read=read(fin,buffer,BUFFER_SIZE)){ if((bytes_read==-1)&&(errno!=EINTR)) break; else if(bytes_read>0){ ptr=buffer; while(bytes_write=write(fout,ptr,bytes_read)){ if((bytes_write==-1)&&(errno!=EINTR)) break; else if(bytes_write==bytes_read) break; else if(bytes_write>0){ ptr+=bytes_write; bytes_read-=bytes_write; } } if(bytes_write==-1) break; } } close(fin); close(fout); return;}main(){ struct timeval tv; struct timezone tz; long time_start,time_end; gettimeofday(&tv,&tz); time_start = tv.tv_sec*1000000 + tv.tv_usec; my_copy1(); printf("\ndone.\n\n"); gettimeofday(&tv,&tz); time_end = tv.tv_sec*1000000 + tv.tv_usec; printf("using \"mmap()\" to copy costs %ld microseconds \n",time_end - time_start); gettimeofday(&tv,&tz); time_start = tv.tv_sec*1000000 + tv.tv_usec; my_copy2(); gettimeofday(&tv,&tz); time_end = tv.tv_sec*1000000 + tv.tv_usec;//这块之前有时会出现打印出的负数,后来查看gettimeofday()函数,才知道,我所使用的微秒位在满一秒//的时候会进位到秒,也即是微秒位清零。所以,正确的方法是在计算time_start和time_end的时候加上//秒这一位,不过要首先转换其成为微秒。 printf("using \"read() and write()\" to copy costs %ld microseconds \n",time_end - time_start);}
调试程序时可以将BUFFER_SIZE
随意更改一个数字,表示的是使用read函数从文件中一次读取的字符个数。当然,强调了这个必然有原因。
如果BUFFER_SIZE很小的话,最终的结果差别很大。比如我的
BUFFER_SIZE=1时我的运行结果如下:
zhou@zhou:~/LinuxC/file/mmcopy$ ./mmap
done.
using "mmap()" to copy costs 591 microseconds
using "read() and write()" to copy costs 505337 microseconds
zhou@zhou:~/LinuxC/file/mmcopy$
两个完全不是一个数量级的。下面换个数字
BUFFER_SIZE=10000时我的运行情况如下:
zhou@zhou:~/LinuxC/file/mmcopy$ ./mmap
done.
using "mmap()" to copy costs 594 microseconds
using "read() and write()" to copy costs 585 microseconds
zhou@zhou:~/LinuxC/file/mmcopy$
这时两个的消耗时间很接近,可以想象。如果BUFFER_SIZE定义的很大的话,那么read()write()方法将会
非常快,但是。如果你要拷贝的文件很小呢,加入只有100字节,但是你却每次申请10000个字节,这样岂不
是很浪费内存。这也就是mmap()的优势,不仅没有浪费内存,而且速度相当的快。
话题一转,这是为什么呢,我的理解使这样的:mmap首先将要拷贝的文件的内容全部映射到内存,然后写到目
的文件,总共的磁盘操作就两次,而read()write()不同,会根据你的BUFFER_SIZE定义的,然后会执行
(文件内容的总的字节数/BUFFER_SIZE)*2 次的磁盘操作,因此在这上面浪费了大量的时间。
- mmap拷贝文件
- 利用mmap实现文件拷贝
- 使用mmap实现文件的拷贝
- mmap多进程拷贝大文件
- 使用存储映射I/O函数mmap进行文件拷贝
- mmap实现多进程对大文件拷贝
- 利用mmap()写一个拷贝文件的程序
- 使用mmap()和使用 read()write()实现文件拷贝的对比
- 使用mmap复制文件
- mmap() 实现文件复制
- 文件映射mmap
- linux mmap 映射文件
- mmap---关于读写文件
- Java文件映射[Mmap]揭秘
- 文件空间映射mmap()函数
- Java文件映射[Mmap]揭秘
- 使用mmap实现文件映射
- mmap实现大文件复制
- 编程代码规范及命名规则
- SQLite操作语句
- 学习SVN版本控制与恢复删除
- http://blog.chinaunix.net/uid-25737580-id-3182286.html
- 第七章 数据字典
- mmap拷贝文件
- 利用HTML5新特性改变浏览器地址后不刷新页面
- [转] 寒门再难出贵子
- hdu 1251 字典树
- PHPDocumentor安装与使用
- Android学习-各种对话框
- rsync+inotify实现实时同步
- Hibernate主键生成策略
- Iframe不能解析mht格式文件