Linux 父子进程实现复制文件内容到另一个文件内
1. 子进程先拷贝前一半 ,父进程一直阻塞到子进程拷贝完再拷贝后一半
/* 子进程先拷贝前一半文件,父进程先阻塞等待子进程拷贝完前一半内容, * 然后父进程在拷贝,后一半内容 * */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/wait.h> //pid_t fork(void); int main(int argc, const char *argv[]) { int fd_r, fd_w; char buf[5] = {0}; int status; fd_r = open(argv[1],O_RDONLY); //打开读取内容的文件 if(fd_r < 0) { perror("read file open fail : "); return -1; } fd_w = open(argv[2],O_WRONLY | O_APPEND,0666); //打开要写入的文件 if(fd_w < 0) { perror("write file open fail : ");close(fd_r); return -1; } off_t fileSize = 0;//文件大小 fileSize = lseek(fd_r,0,SEEK_END) - lseek(fd_r,0,SEEK_SET);//读取源文件有多少个字符:w printf("源文件大小:%ld\n",fileSize); off_t c_read_size;//子进程,读取文件的大小 c_read_size = fileSize / 2; off_t f_read_size;//父进程,读取文件的大小 f_read_size = fileSize - c_read_size; #if 1 pid_t pid ; pid = fork(); if(pid == -1) {perror("pid fail : "); exit(1);} else if(pid == 0)//子进程 { printf("子进程开始\n"); printf("子进程读取大小:%ld\n",c_read_size); ssize_t size_cnt = 0;//记录读取的个数 ssize_t temp_size = 0;//临时读取记录 while(1) //循环读,读取到中间位置 { temp_size = read(fd_r,buf,1); if(temp_size <= 0)//没有读取到数据,或者读取出错 { printf("child read fail or end\n"); break; } ssize_t tt =0; //子进程写入失败 tt = write(fd_w,buf,1); //读取到 数据写入文件 if(tt ==-1) { perror("child write file fail :"); break; } size_cnt = size_cnt + temp_size; if(size_cnt >= c_read_size) //读取到该读的数据 { printf("child write file end \n"); break; } } exit(1); //退出子进程 } else //父进程 { waitpid(pid, &status, 0);//等待子进程执行完在执行 printf("父进程开始\n"); printf("父进程读取大小:%ld\n",f_read_size); lseek(fd_r,-f_read_size,SEEK_END);//相对文件末尾向移动到,子进程读取的位置 while(1)//开始读取数据 { ssize_t f_read_size; f_read_size = read(fd_r,buf,1); if(f_read_size <= 0)//读取到末尾返回值为 0 { printf("father read file end\n"); break; } ssize_t t =0; //父进程写入失败 t = write(fd_w,buf,1); if(t ==-1) { perror("father write file fail : "); break; } } printf("father write file end \n"); exit(1); } #endif close(fd_r); close(fd_w); return 0; }
测试:
2. 父子进程同时拷贝,父进程拷贝前一半,子进程拷贝后一半,写文件的顺序不确定,所以写入后内容会乱
/* copy文件,父进程先拷贝前一半,子进程拷贝后一半 * 文件内容可以完整拷贝,写数据时顺序会打乱 * 父进程写一点,子进程写一点 * */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/wait.h> int main(int argc, const char *argv[]) { int fd_r,fd_w; off_t size; char ch = '\0'; pid_t pid; char buf[64] = {0}; ssize_t tmp = 0; if((fd_r = open(argv[1],O_RDONLY)) == -1) { perror("fcntlail to open fd_r"); exit(1); } if((fd_w = open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0666)) == -1) //打开写的文件,没有就创建,有内容就清空,只写方式打开 { close(fd_r); perror("fail to open FD_ZEROBASED_w"); exit(1); } size = lseek(fd_r,0,SEEK_END); lseek(fd_w,size - 1,SEEK_SET); write(fd_w,&ch,1);//在文件的末尾先添加一个 '\0' 结尾符,确定写文件的大小 size /= 2; //size = size / 2; //文件大小的一半 pid = fork(); if(pid < 0) { perror("fail to fork"); exit(1); } else if(pid == 0) //子进程拷贝后一半 { lseek(fd_r,size,SEEK_SET); lseek(fd_w,size,SEEK_SET); while((tmp = read(fd_r,buf,sizeof(buf))) > 0) { write(fd_w,buf,tmp); } close(fd_r); close(fd_w); exit(0); } else //父进程,拷贝前一半 { lseek(fd_r,0,SEEK_SET); lseek(fd_w,0,SEEK_SET); while(1) { if(size > sizeof(buf)) { tmp = read(fd_r,buf,sizeof(buf)); } else { tmp = read(fd_r,buf,size); } if(tmp <= 0) { break; } size -= tmp;//size = size - tmpfd_w; write(fd_w,buf,tmp); } wait(NULL);//等待回收子进程 close(fd_r); close(fd_w); } return 0; }