多进程拷贝文件

多进程实现文件拷贝

复制方式
  • ./processsrc_file process_num(进程数名称输入:0~100)

有两个.c文件,分别是ProcessCopy.cmycp.c,其中mycp.c是一个拷贝文件,默认只有一个进程,具体拷贝程序的流程数可以通过传参来确定。

ProcessCopy.c 程序

该程序主要分为创建子流程,ECEC函数重载mycp.c函数,回收子进程空间,错误处理等几部分。

在子进程中进行拷贝时,通过<ProcessNum来文件子进程进行拷贝。

mycp.c程序

1.该程序主要完成对文件的拷贝工作。

2.拷贝的进程数可以通过EXEC函数传递,传递时将进程编号一并传递,来辨别是时间子进程,以便计算偏移位置。

3.通过lseek来计算子过程读取和写入的轨迹位置。

4.在拷贝时,需要计算过程中需要拷贝源的字节数wNum,由于文件的总字节数特别能整除过程数,因此如果不能整除需要wNum+1处理。

5.设置每个flag来标记进程已经拷贝的字节数,当flag>wNum时,需要设置拷贝的字节数为wSize = wSize - (flag-rsize),复制完成后退出,此过程复制工作完成

拷贝文件进程

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>

//错误码
enum ecode_err{
	argument_list_err,
	src_open_err,
	des_open_err,
	cop_fin
};

int main(int argc,char **argv)
{
	//错误处理
	if(argc < 3)
	{
		printf("请输入源文件和目标文件!\n");
		exit(argument_list_err);
	}
	int ProcessNum = 1;
	int nCount = 0;//标记第几个进程

	//字符转数字
	if(argc > 4)
	{
		ProcessNum = atoi(argv[3]);
		nCount = (int)*argv[4];
	}
	//文件描述符
	int sfd = open(argv[1],O_RDONLY);//源文件
	if(sfd < 0)
	{
		perror("open src error!\n");
		exit(src_open_err);
	}

	int dfd = open(argv[2],O_WRONLY | O_CREAT,0664);//目标文件
	if(dfd < 0)
	{
		perror("open des error!\n");
		exit(des_open_err);
	}

	//计算文件大小
	int fileSize = lseek(sfd,0,SEEK_END);

	//计算子进程需要拷贝的起点和大小
	int wNum = fileSize/ProcessNum;
	//文件可能不会被进程整除,因此不能除近时每个进程多拷贝一个
	wNum = fileSize%ProcessNum == 0 ? wNum : wNum+1;

	//读取数据缓冲区大小
	char buffer[8192] = {0};
	//读取的字节数和每个进程总共读取字节数标志
	int rsize;
	int flag = 0;

	//设置每个进程读取和写入的偏移指针位置
	int rseek = lseek(sfd,wNum*nCount,SEEK_SET);
	int wseek = lseek(dfd,wNum*nCount,SEEK_SET);

	while((rsize = read(sfd,buffer,sizeof(buffer)))!= 0)
	{
		flag += rsize;
		if(flag >= wNum)
		{
			//如果读取的数据大于要每个进程要写入的数据wNum
			rsize = wNum - (flag - rsize);
			write(dfd,buffer,rsize);
			//每一个进程拷贝结束后都要关闭自己的文件,描述符
			close(sfd);
			close(dfd);
			break;
			//exit(red_fin);
		}
		write(dfd,buffer,rsize);
	}
	//每一个进程拷贝结束后都要关闭自己的文件,描述符
	close(sfd);
	close(dfd);

	return cop_fin;
}

父进程创建的子进程重载(exec)拷贝进程

#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>

//错误码
enum ecode_err{
	argument_list_err = 3,
	argument_many,
	ProcessNum_err,
	fork_err,
};

int main(int argc,char **argv)
{
	//校验传入参数
	if(argc < 3)
	{
		printf("请输入要拷贝的源文件和目标文件!(进程数可选择是否输入:0~100)\n");
		exit(argument_list_err);
	}
	if(argc > 4)
	{
		printf("最多传三个参数!\n");
		exit(argument_many);
	}

	int ProcessNum = 5;//默认创建5个进程

	if(argc == 4)
	{
		ProcessNum = atoi(argv[3]);
	}

	//校验用户输入的线程数
	if(ProcessNum <= 0 || ProcessNum >= 100)
	{
		printf("请输入0~100之间内的进程数\n");
		exit(ProcessNum_err);
	}
	/*-----------------------------------开始拷贝------------------------------------*/
	//创建子进程
	pid_t pid;
	int i;
	for(i = 0;i < ProcessNum;i++)
	{
		pid = fork();
		//子进程跳出循环,只有父进程来创建进程
		if(pid == 0)
			break;
	}
	if(pid < 0)	
	{
		perror("parent call fork fail...\n");
		exit(fork_err);
	}
	/*---------子进程拷贝--------------*/
	if(i < ProcessNum)//子进程
	{
		char *argv1[] = {"copy",argv[1],argv[2],argv[3],(char*)&i,NULL};
		int ecode = execv("copy",argv1);
	}

	/*-----------------------------回收子进程空间------------------------------------------*/
	pid_t wpid;
	int status;
	int ecode;
	while((wpid = waitpid(-1,&status,WNOHANG)) != -1)
	{
		if(wpid > 0)
		{
			//子进程正常退出
			if(WIFEXITED(status))
			{
				ecode = WEXITSTATUS(status);
				printf("child wait success pid = %d  ecode = %d\n",wpid,ecode);
			}
			else if(WIFSIGNALED(status))//信号杀死
			{
				ecode = WTERMSIG(status);
				printf("child waip sig pid = %d   ecode = %d\n",wpid,ecode);
			}
		}
	}

	while(1);

	return 0;
}

GitHub链接
获取源码点击这里

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bug.Remove()

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值