大文件拷贝
假设有一个超大文件,需对其完成拷贝工作。为提高效率,可采用多进程并行拷贝的方法来实现。假设文件 大小为 len,共有 n 个进程对该文件进行拷贝。那每个进程拷贝的字节数应为 len/n。但未必一定能整除,我们可 以选择让最后一个进程负责剩余部分拷贝工作。可使用 len%(len/n)将剩余部分大小求出。
为降低实现复杂度,可选用 mmap 来实现源、目标文件的映射,通过指针操作内存地址,设置每个进程拷贝 的起始、结束位置。借助 MAP_SHARED 选项将内存中所做的修改反映到物理磁盘上
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<fcntl.h>
#include<sys/mman.h>
#include<stdlib.h>
#include<string.h>
#include<sys/stat.h>int main(int argc,char *argv[])
{int n=5;//输入参数至少是3,第四个参数可以是进程个数if(argc<3){printf("./a.out src dst [n]\n");return 0;} if(argc==4){n=atoi(argv[3]);} //打开源文件int srcfd=open(argv[1],O_RDONLY);if(srcfd<0){perror("open err");exit(1);} //打开目标文件int dstfd=open(argv[2],O_RDWR|O_CREAT|O_TRUNC,0644);if(dstfd<0){perror("open dst err");exit(1);} //目标拓展,从原文件获得文件大小,statstruct stat sb; stat(argv[1],&sb);//为了计算大小int len=sb.st_size;truncate(argv[0],len);//将源文件映射到缓冲区char *psrc = mmap(NULL,len,PROT_READ,MAP_SHARED,srcfd,0);
if(psrc == MAP_FAILED){perror("mmap dst err");exit(1);}//将目标文件映射char *pdst = mmap(NULL,len,PROT_READ|PROT_WRITE,MAP_SHARED,dstfd,0);if(pdst == MAP_FAILED){perror("mmap dst err");exit(1);}//创建多个子进程int i=0;for(i=0;i<n;i++){if(fork()==0)break;}//计算子进程需要拷贝的起点和大小int cpsize=len/n;int mod=len%n;//数据拷贝 ,memcpyif(i<n){ //子进程if(i== n-1){ //最后一个子进程memcpy(pdst+i*cpsize,psrc+i*cpsize,cpsize+mod);}else{memcpy(pdst+i*cpsize,psrc+i*cpsize,cpsize);}}else{for(i=0;i<n;i++){wait(NULL);}}
//释放映射区if(munmap(psrc,len)<0){perror("munmao src err");exit(1);}//关闭文件close(srcfd);close(dstfd);return 0;
}