进程Day040818

目录

1.使用两个进程完成两个文件的拷贝,父进程拷贝前一半内容,子进程拷贝后一半内容,并且父进程要阻塞回收子进程资源

代码

运行结果

2.使用三个进程完成两个文件的拷贝,父进程拷贝前三分之一,子进程1拷贝中间三分之一,子进程2拷贝后三分之一,父进程要阻塞回收所有子进程资源

代码

运行结果

3.思维导图


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;
}
运行结果

 

3.思维导图

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值