Linux多进程文件拷贝(C/C++)——方案二(使用mmap内存映射)
#include <iostream>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
using namespace std;
int main(int argc,char* argv[])
{
if(argc < 4) {
cout << "Usage: ./a.out fileSrcPath fileDestPath processNumber" << endl;
return 0;
}
int srcfd = open(argv[1],O_RDONLY);
if(srcfd == -1) {
perror("open src error");
return -1;
}
int len = lseek(srcfd,0,SEEK_END);
//cout << "src len = " << len << endl;
if(len == -1) {
perror("lseek src error");
return -1;
}
char* ptr_r = (char*)mmap(NULL,len,PROT_READ,MAP_SHARED,srcfd,0);
if(ptr_r == MAP_FAILED) {
perror("mmap src error");
return -1;
}
close(srcfd);
int desfd = open(argv[2],O_RDWR|O_CREAT,0664);
if(desfd == -1) {
perror("open des error");
return -1;
}
//也可以使用lseek,最后必须写点东西才行,否则会报Bus Error(总线错误)
int ret = ftruncate(desfd,len);
//cout << "des len = " << len << endl;
if(ret == -1) {
perror("ftruncate error");
return -1;
}
char* ptr_w = (char*)mmap(NULL,len,PROT_WRITE,MAP_SHARED,desfd,0);
close(desfd);
if(ptr_w == MAP_FAILED) {
perror("mmap des error");
return -1;
}
int i; pid_t pid;
//传进来的argv[3]参数是总进程数,所以创建argv[3]-1个子进程
int childPronum = atoi(argv[3])-1;
//将文件分为总进程数量个块
int eachSize = len/(childPronum+1);
for(i=0;i<childPronum;i++) {
pid = fork();
if(pid == -1) {
perror("fork error");
return -1;
} else if(pid == 0) {
break;
}
}
//子进程拷贝前childPronum 份等长数据
while(pid == 0 && childPronum--) {
if(i == childPronum) {
memcpy(ptr_w+i*eachSize,ptr_r+i*eachSize,eachSize);
cout << "child_" << i << "'s pid = " << getpid() << ",writes bytes = " << eachSize << endl;
break;
}
}
//父进程拷贝最后一份长度不确定数据
if(pid > 0 && i == childPronum) {
memcpy(ptr_w+i*eachSize,ptr_r+i*eachSize,len-i*eachSize);
cout << "i = " << i << " parent's pid = " << getpid() << ",writes bytes = " << len-i*eachSize << endl;
}
if(munmap(ptr_r,len) == -1 || munmap(ptr_w,len) == -1) {
perror("munmap error");
return -1;
}
return 0;
}
若有误请指出,谢谢