目录
1.使用两个进程完成两个文件的拷贝,父进程拷贝前一半内容,子进程拷贝后一半内容,并且父进程要阻塞回收子进程资源
2.使用三个进程完成两个文件的拷贝,父进程拷贝前三分之一,子进程1拷贝中间三分之一,子进程2拷贝后三分之一,父进程要阻塞回收所有子进程资源
1.使用两个进程完成两个文件的拷贝,父进程拷贝前一半内容,子进程拷贝后一半内容,并且父进程要阻塞回收子进程资源
代码
#include<myhead.h>
int main(int argc, const char *argv[])
{
//判断输入是否合法,如果不合法则输出正确格式并且结束程序
if(3!=argc){
printf("The number of arguments error!\n");
printf("Usage:./a.out srcfileName dstfileName\n");
return -1;
}
//创建一个进程号类型的变量
pid_t pid;
//创建指向被复制文件的文件指针
FILE *srcfp;
//创建指向目标文件的文件指针
FILE *dstfp;
//打开被复制文件并且判断是否成功打开,失败则输出错误码并结束程序
if(NULL==(srcfp = fopen(argv[1],"r"))){
perror("fopen error");
return -1;
}
//打开目标文件并且判断是否成功打开,失败则输出错误码并结束程序
if(NULL==(dstfp = fopen(argv[2],"w+"))){
perror("fopen error");
return -1;
}
//文件内容计数
int count = 0;
char buf;
//每次只读取一字节,读取到就计数加1,没读取到内容就说明结束.
while(fread(&buf,1,1,srcfp)>0){
count++;
}
int halfCount = count/2;
//计数结束之后要将指针归位
fseek(srcfp,0,SEEK_SET);
//创建子进程
pid = fork();
//判断逻辑
if(pid < 0){
//如果pid小于0说明子进程创建失败,输出错误信息并结束程序
perror("fork error");
return -1;
}else if(0 == pid){
//pid等于0,说明当前正运行在子进程中
//定义一个变量记录已经写入了多少个字符
int countChild = 0;
//定义一个在子进程中使用的搬运工
int bufChild = 0;
//重定向到文件开头往后halfcount位置
//根据父进程的循环条件可知,写到了halfcount位置的前一个字符位置,
//所以应该重定向到halfcount位置
fseek(srcfp,halfCount,SEEK_SET);
fseek(dstfp,halfCount,SEEK_SET);
printf("\n*****这是子进程*****\n");
//当读取到文件结尾或者读取计数计完剩下的值后结束
//这里主要两个判断条件应该是同时满足的,写哪一个都行
//都写上双保险
while(EOF!=(bufChild=fgetc(srcfp))&&countChild<(count-halfCount)){
//在终端中输出,有一个可视的过程
printf("%c",bufChild);
fputc(bufChild,dstfp);
//写入字符计数
countChild++;
}
//关闭文件
fclose(dstfp);
printf("\n*****这是子进程*****\n");
//子进程结束,返回结束信号
exit(EXIT_SUCCESS);
}else{
//挂起等待子进程的结束,确保父进程能够活到给子进程收尸
//并且保证程序执行的先后顺序
wait(NULL);
//pid等于0,说明当前正运行在父进程中
//定义一个变量记录已经写入了多少个字符
int countFather = 0;
//定义一个在父进程中使用的搬运工
char bufFather = 0;
//将文件指针重定向到文件开头
//父进程只写文件的前半部分
fseek(srcfp,0,SEEK_SET);
fseek(dstfp,0,SEEK_SET);
printf("\n*****这是父进程*****\n");
//当读取到结束或者写入的字符数超过一半时停止,在这个进程中,起作用的主要
//是字符数计数的条件,因为只写前一半
while(EOF!=(bufFather=fgetc(srcfp))&&countFather<halfCount){
printf("%c",bufFather);
fputc(bufFather,dstfp);
//计数自增
countFather++;
}
//关闭文件
fclose(dstfp);
printf("\n*****这是父进程*****\n");
}
//printf("被复制文件%s和目标文件%s打开成功\n",argv[1],argv[2]);
//测试
//printf("count = %d\n",count);
return 0;
}
运行结果
2.使用三个进程完成两个文件的拷贝,父进程拷贝前三分之一,子进程1拷贝中间三分之一,子进程2拷贝后三分之一,父进程要阻塞回收所有子进程资源
代码
#include<myhead.h>
int main(int argc, const char *argv[])
{
//判断输入是否合法,如果不合法则输出正确格式并且结束程序
if(3!=argc){
printf("The number of arguments error!\n");
printf("Usage:./a.out srcfileName dstfileName\n");
return -1;
}
//创建一个进程号类型的变量
pid_t pid;
//创建指向被复制文件的文件指针
FILE *srcfp;
//创建指向目标文件的文件指针
FILE *dstfp;
//打开被复制文件并且判断是否成功打开,失败则输出错误码并结束程序
if(NULL==(srcfp = fopen(argv[1],"r"))){
perror("fopen error");
return -1;
}
//打开目标文件并且判断是否成功打开,失败则输出错误码并结束程序
if(NULL==(dstfp = fopen(argv[2],"w+"))){
perror("fopen error");
return -1;
}
//文件内容计数
int count = 0;
char buf;
//每次只读取一字节,读取到就计数加1,没读取到内容就说明结束.
while(fread(&buf,1,1,srcfp)>0){
count++;
}
int oneThirdCount = count/3;
int twoThirdCount = count*2/3;
//计数结束之后要将指针归位
fseek(srcfp,0,SEEK_SET);
//创建子进程
pid = fork();
//判断逻辑
if(pid < 0){
//如果pid小于0说明子进程创建失败,输出错误信息并结束程序
perror("fork error");
return -1;
}else if(0 == pid){
//子进程中再次创建一个子进程,定义孙子进程的进程号变量
pid_t gpid;
//在这个程序中,这是孙子进程
gpid = fork();
//判断逻辑
if(gpid < 0){
//如果pid小于0说明子进程创建失败,输出错误信息并结束程序
perror("fork error");
return -1;
}else if(0 == gpid){
//pid为0且gpid为0说明这是子进程的子进程,称之为孙子进程
//定义一个变量记录已经写入了多少个字符
int countGrandChild = 0;
//定义一个在孙子进程中使用的搬运工
int bufGrandChild = 0;
//重定向到文件开头往后twoThirdCount位置
//根据子进程的循环条件可知,写到了twoThirdCount位置的前一个字符位置,
//所以应该重定向到twoThirdCount位置
fseek(srcfp,twoThirdCount,SEEK_SET);
fseek(dstfp,twoThirdCount,SEEK_SET);
printf("\n*****这是孙子进程*****\n");
//当读取到文件结尾或者读取计数计完剩下的值后结束
//这里主要两个判断条件应该是同时满足的,写哪一个都行
//都写上双保险
while(EOF!=(bufGrandChild=fgetc(srcfp))&&countGrandChild<(count-twoThirdCount)){
//在终端中输出,有一个可视的过程
printf("%c",bufGrandChild);
fputc(bufGrandChild,dstfp);
//写入字符计数
countGrandChild++;
}
//关闭文件
fclose(dstfp);
printf("\n*****这是孙子进程*****\n");
//孙子进程结束,返回结束信号,让其父,也就是这个程序中的子进程进行收尸
exit(EXIT_SUCCESS);
}else{
//pid等于0,但是gpid>0,说明当前正运行在子进程中
//挂起等待孙子进程结束后给他收尸并且确保程序的运行顺序
wait(NULL);
//定义一个变量记录已经写入了多少个字符
int countChild = 0;
//定义一个在子进程中使用的搬运工
int bufChild = 0;
//将文件指针重定向到文件oneThirdCount位置,由父进程的判断条件可知
//父进程写到oneThirdCount的前一个字符位置,所以子进程要从oneThirdCount位置开始
//子进程只写文件的中间1/3部分
fseek(srcfp,oneThirdCount,SEEK_SET);
fseek(dstfp,oneThirdCount,SEEK_SET);
printf("\n*****这是子进程*****\n");
//当读取到结束或者写入的字符数超过中间1/3时停止,在这个进程中,起作用的主要
//是字符数计数的条件,因为只写中间1/3
while(EOF!=(bufChild=fgetc(srcfp))&&countChild<(twoThirdCount-oneThirdCount)){
//在终端中输出,有一个可视的过程
printf("%c",bufChild);
fputc(bufChild,dstfp);
//写入字符计数
countChild++;
}
//关闭文件
fclose(dstfp);
printf("\n*****这是子进程*****\n");
//子进程结束,返回结束信号
exit(EXIT_SUCCESS);
}
}else{
//pid等于0,说明当前正运行在父进程中
//挂起等待子进程的结束,确保父进程能够活到给子进程收尸
//并且保证程序执行的先后顺序
wait(NULL);
//定义一个变量记录已经写入了多少个字符
int countFather = 0;
//定义一个在父进程中使用的搬运工
char bufFather = 0;
//将文件指针重定向到文件开头
//父进程只写文件的前1/3部分
fseek(srcfp,0,SEEK_SET);
fseek(dstfp,0,SEEK_SET);
printf("\n*****这是父进程*****\n");
//当读取到结束或者写入的字符数超过1/3时停止,在这个进程中,起作用的主要
//是字符数计数的条件,因为只写前1/3
while(EOF!=(bufFather=fgetc(srcfp))&&countFather<oneThirdCount){
printf("%c",bufFather);
fputc(bufFather,dstfp);
//计数自增
countFather++;
}
//关闭文件
fclose(dstfp);
printf("\n*****这是父进程*****\n");
}
//printf("被复制文件%s和目标文件%s打开成功\n",argv[1],argv[2]);
//测试
//printf("count = %d\n",count);
return 0;
}
运行结果