🔥 博客主页: 我要成为C++领域大神
🎥系列专栏:【C++核心编程】 【计算机网络】 【Linux编程】 【操作系统】
❤️感谢大家点赞👍收藏⭐评论✍️本博客致力于分享知识,欢迎大家共同学习和交流。
为什么要进行多进程拷贝?
这涉及到了分时复用原理。
分时复用原理
分时复用:在多进程环境下,进程在时间片内与CPU进行交互,时间片用完时进程会被中断,等待下一次CPU使用权限。
时间片:每个进程在运行时会被分配一个时间片,时间片用完后CPU会切换到另一个进程。
多进程拷贝优势:通过多进程处理,可以更高效地利用系统资源(CPU、内存),减少大文件拷贝任务的完成时间。
执行方式对比
串行执行:任务严格按顺序执行,从头到尾依次处理。
优点:简单、易实现。
缺点:不能充分利用系统资源,效率低。
并发执行:多个任务在同一时间段内执行,但不一定同时进行,利用CPU切换完成多个任务。
优点:比串行执行更高效,能更好地利用CPU。
缺点:需要处理进程间的通信和同步问题。
并行执行:物理上同时进行,多个核心或处理器同时执行多个任务。
优点:最高效的执行方式,可以显著缩短任务完成时间。
缺点:需要多核或多处理器支持,复杂度更高。
不要频繁的进程切换,频繁切换会浪费开销,影响系统性能。
多进程可以加快任务完成速度,但需要合理的任务分配和资源管理。
多进程拷贝的优点
1. 提高文件拷贝效率
并行处理:多进程拷贝通过并行处理文件的不同部分,可以显著提高拷贝速度,尤其是对于大文件而言。
减少I/O等待时间:多个进程可以同时进行读取和写入操作,减少了单个进程的I/O等待时间,提高整体效率。
2. 充分利用系统资源
多核CPU的利用:现代计算机通常配备多核CPU,多进程拷贝可以同时利用多个CPU核心,避免资源闲置。
内存利用:多进程可以更好地利用系统内存和缓存,提高数据处理效率。
3. 提高系统响应性
负载分散:通过将文件拷贝任务分散到多个进程,可以减小单个进程的负载,使系统在执行大文件拷贝时仍能保持较好的响应性。
任务中断与恢复:多进程模式下,如果某个进程失败,只需重新启动该进程或重新分配任务,而不必重新开始整个文件拷贝,提高了拷贝任务的健壮性。
应用场景
在需要拷贝超大文件时,单进程的处理速度较慢,而多进程可以显著加快拷贝速度。
在需要同时执行多个文件拷贝任务的场景,多进程可以同时处理多个任务,提高整体处理效率。
多进程拷贝的流程
Process_Copy.c
命令行参数:
Process_Copy
的输入包括源文件路径、目标文件路径、进程数量(可选,默认为5)。参数校验:程序首先会检查参数数量和文件路径的有效性。
任务量计算:通过计算源文件大小和进程数量来确定每个进程处理的字节数,处理任务被分成多块。
多进程创建:根据用户指定的进程数量,创建多个子进程(
cp_process
)。文件分块:源文件、目标文件、任务量和进程数被传递给每个子进程,子进程负责处理指定块的文件拷贝。
进程重载:对每个子进程使用execl函数进行重载,让其实现
copy.c
的功能。
关于execl函数的使用,可以看我这期博客【Linux】execl函数详解|进程重载
Copy.c
任务接收与处理:接收任务并进行位置转换,以便正确处理文件偏移量。
文件操作:
打开文件:以读方式打开源文件,以写方式打开目标文件。
文件指针调整:将源文件和目标文件的指针移动到指定位置,确保正确的读取和写入。
读写操作:读取源文件的数据并写入到目标文件中。
关闭文件:完成操作后,关闭文件描述符并退出进程。
流程
执行 Process_Copy
,传入源文件路径、目标文件路径,多线程数量。
Process_Copy
计算每个进程的任务量,创建并分配子进程。
每个子进程通过 Copy
执行文件拷贝任务,处理源文件和目标文件的读写操作。
- 参数校验 -> 任务量计算 -> 进程创建 -> 子进程执行文件拷贝。
- 子进程根据任务量和位置执行读写操作,直到完成整个文件的拷贝。
代码实现
Process_Copy.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <string.h>
#include <sys/fcntl.h>
#include <sys/wait.h> /* 多进程拷贝样例 */
int Block_Cur(const char* File_Name,int Pro_Number)
{/* 计算每个进程应该拷贝的大小 */int fd;if((fd=open(File_Name,O_RDONLY))==-1){perror("Block_Cur>>file open fail");exit(0);}int fsize;if((fsize=lseek(fd,0,SEEK_END))==-1){perror("Block_Cur>>get filesize fail");exit(0);}if(fsize%Pro_Number==0)return fsize/Pro_Number;else return fsize/Pro_Number+1;}/* Process_Copy SRC DES 30,进程数量可缺省 */
int Check_Pram(int Arg_No,const char* Src_File,int Pro_Number)
{if(Arg_No<3){printf("Error:Pram Error\n");exit(0);}if(access(Src_File,F_OK)!=0){printf("Error:Src_File Not Exist\n");exit(0);}if(Pro_Number<=0 || Pro_Number>80){printf("Error:Pro_Number is Limited\n");exit(0);}return 0;
}int Process_Create(const char* Src_File,const char *Des_File,int Pro_Number,int Blocksize)
{pid_t pid;int i;/* 循环创建空格 */for(i=0;i<Pro_Number;++i){pid=fork();if(pid==0) break;}if(pid>0){/* 父进程工作区 */printf("Parent Process PID:%d wait...\n",getpid());/* 回收僵尸进程 */pid_t zpid;while((zpid=wait(NULL))>0){printf("wait sucess,ZPID:%d\n",zpid);}}else if(pid==0){/* 子进程工作区 */int pos=0;pos=i*Blocksize;char str_Blocksize[10];char str_pos[10];bzero(str_Blocksize,10);bzero(str_pos,10);sprintf(str_Blocksize,"%d",Blocksize);sprintf(str_pos,"%d",pos);execl("/home/cppstudy/code/PROCESS/Process_Copy/copy","copy",Src_File,Des_File,str_Blocksize,str_pos,NULL);}else{perror("fork call failed");exit(0);}
}
int main(int argc,char** argv)
{ int Pro_Number=0;if(argv[3]==0) Pro_Number=5;else Pro_Number=atoi(argv[3]);/* 参数校验 */Check_Pram(argc,argv[1],Pro_Number);/* 任务量分割 */int Block_Size=Block_Cur(argv[1],Pro_Number);/* 进程创建 */Process_Create(argv[1],argv[2],Pro_Number,Block_Size);return 0;
}
Copy.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <string.h>
#include <sys/fcntl.h>int main(int argc,char**argv)
{int blocksize;int pos;ssize_t len;int sfd;int dfd;blocksize=atoi(argv[3]);pos=atoi(argv[4]);char buffer[blocksize];bzero(buffer,sizeof(buffer));printf("Child Process PID:%d copy sucess,File_Name:%s,Blocksize:%d,pos:%d\n",getpid(),argv[1],blocksize,pos);if((sfd=open(argv[1],O_RDONLY))==-1){printf("%s open fail\n",argv[1]);exit(0);}if((dfd=open(argv[2],O_RDWR|O_CREAT,0664))==-1){printf("%s create fail\n",argv[2]);exit(0);}/* 读写指针偏移位置 */lseek(sfd,pos,SEEK_SET);lseek(dfd,pos,SEEK_SET);len=read(sfd,buffer,sizeof(buffer));write(dfd,buffer,len);close(sfd);close(dfd);return 0;
}
运行结果