• linux下多进程的文件拷贝与进程相关的一些基础知识


    之前实现了用文件IO的方式能够实现文件的拷贝,那么对于进程而言,我们是否也能够实现呢?

    答案是肯定的。

    进程资源:

    首先我们先回想一下,进程的执行须要哪些资源呢?其资源包含CPU资源,内存资源,当然还有时间片资源。我们都知道进程是有 栈。 堆,  仅仅读数据段,  数据段(已初始化的全局变量静态变量),bss段(未初始化的),   代码段另一组寄存器值。

    进程命令:

    另外我们也能够通过 ps  -ef |grep 进程名命令来查看进程号(PID)和父进程号(PPID),之后还能够通过  

    ps aux |grep 进程名或进程号来查看进程的状态(R,T,S,Z,(+)...).通过 kill -信号的序号或宏  PID来对信号发各种信号。注意这里面的kill可不是杀死进程的意思。我们能够通过给进程发信号来杀死进程kill -SIGKILL PID  ,当然我们能够通过 kill -l 来获取宏名,其次我们通过nice 或renice来给我们的进程设置不同的优先级,等等等等。

    进程创建:

    我们会用fork函数来创建进程,曾经我们都非常清除的知道,一个函数仅仅能够返回一个返回值。那么进程创建的函数也仅仅返回一个么?答案是不正确的,由于通过fork函数创建的进程,假设成功的话我们向父进程返回子进程的PID号,向子进程返回0,假设创建失败,则向父进程返回-1。

    创建完子进程后。父进程从fork()的下一条语句開始运行,子进程也是从下一条语句运行么?

    是的,由于创建子进程的时候拷贝父进程的pc寄存器值,而pc寄存器的值决定了你的进程是从什么地方開始的。所以当创建完子进程后,我们的子进程的运行与父进程的运行系一样的方式,可是注意他们两个不是一块进行的。也有先后关系,仅仅是先后关系不确定,假设用vfork函数创建进程的话,那么我们的子进程是先进行的。

    那么上面说了fork()函数与vfork()函数都能够创建进程,有什么差别呢?

    <1>fork创建子进程后。父子进程运行的顺序是不确定的,父子进程的地址空间是独立的。

    <2>vfork创建完子进程后,保证子进先运行,父进程在子进程结束。或调用exec函数族后才開始运行。

    而且父子进程共享同一地址空间【假设子进程调用了exec函数则子进程会独立出来】。

    那么如何利用进程来进行文件的拷贝呢?以及如何拷贝呢?详细实现的要求例如以下,父进程复制文件的前一半子进程复制文件的后一半,那么效率上面我们肯定比一个进程高得多了。以上就是对进程知识的相关回想。知识点有了,思路有了。那么剩下的就仅仅是代码实现的问题了。也就是体力劳动了:

    请看以下代码的实现:


      

    #include <head.h>
    
    int child_copy(int fd_src,int fd_dest,int file_size)
    {
    	int ret;
    	int n;
    	char buf[1024];
    	ret = lseek(fd_src,file_size/2,SEEK_SET);
    	if(ret < 0)
    	{
    		perror("Fail to src_file lseek");
    		exit(EXIT_FAILURE);
    	}
    	ret = lseek(fd_dest,file_size/2,SEEK_SET);
    	if(ret < 0)
    	{
    		perror("Fail to dest_file lseek");
    		exit(EXIT_FAILURE);
    	}
    	while(1)
    	{
    		n = read(fd_src,buf,sizeof(buf));
    		if(n == 0)
    			break;
    		write(fd_dest,buf,n);
    	}
    	return 0;
    }
    int parent_copy(int fd_src,int fd_dest,int size)
    {
    	int n;
    	int count = 0;
    	char buf[1024];
    	while(1)
    	{
    	//	lseek(fd_src,0,SEEK_SET);
    	//	lseek(fd_dest,0,SEEK_SET);
    		n = read(fd_src,buf,sizeof(buf));
    		write(fd_dest,buf,n);
    		count += n;
    		if(count >= size/2)
    			break;
    	}
    	return 0;
    }
    // ./a.out src_file dest_file
    int main(int argc, const char *argv[])
    {
    	pid_t pid;
    	int file_size;  //the size of file
    	int fd_src,fd_dest; 
    	struct stat f_info;
    
    	if(argc < 3)
    	{
    		fprintf(stderr,"Usage :%s argv[1] argv[2]
    ",argv[0]);
    		exit(EXIT_FAILURE);
    	}
    	if(stat(argv[1],&f_info) < 0)
    	{
    		fprintf(stderr,"Fail to stat %s: %s",argv[1],strerror(errno));
    		exit(EXIT_FAILURE);
    	}
    	file_size = f_info.st_size; //get the size of file
    	
    	fd_src = open(argv[1],O_RDONLY);//open the file
    	if(fd_src < 0)
    	{
    		fprintf(stderr,"Fail to open %s : %s
    ",argv[1],strerror(errno));
    		exit(EXIT_FAILURE);
    	}
    
    	fd_dest = open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0666);
    	if(fd_src < 0)
    	{
    		fprintf(stderr,"Fail to open %s : %s
    ",argv[2],strerror(errno));
    		exit(EXIT_FAILURE);
    	}
    	
    	if(ftruncate(fd_dest,file_size) < 0)  //create a empty file
    	{
    		perror("fail to ftruncate");
    		exit(EXIT_FAILURE);
    	}
    
    	pid = fork();
    	if(pid < 0)
    	{
    		fprintf(stderr,"Fail to fork
    ",strerror(errno));
    		exit(EXIT_FAILURE);
    	}
    	if(pid == 0)
    	{
    		close(fd_src);
    		close(fd_dest);
    		fd_src = open(argv[1],O_RDONLY);//open the file again
    		if(fd_src < 0)
    		{
    			fprintf(stderr,"Fail to open %s : %s
    ",argv[1],strerror(errno));
    			exit(EXIT_FAILURE);
    		}
    
    		fd_dest = open(argv[2],O_WRONLY);
    		if(fd_src < 0)
    		{
    			fprintf(stderr,"Fail to open %s : %s
    ",argv[2],strerror(errno));
    			exit(EXIT_FAILURE);
    		}
    		
    		child_copy(fd_src,fd_dest,file_size);
    	}
    	if(pid > 0)
    	{
    //		getchar();
    		parent_copy(fd_src,fd_dest,file_size);
    	}
    
    	return 0;
    }
    

        


    注:

    本程序用到的头文件本人直接封装在了head.h中。假设有哪里须要改进希望留言给我哈



  • 相关阅读:
    vue中局部封装axios
    react中key的使用
    react中component存在性能问题
    react中setState用法
    常用函数
    常用正则匹配整理
    Linux设置DNS server
    [多线程]wait和notify
    [多线程]脏读
    [多线程]线程基础(对象锁、class锁、同步、异步)
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/7112699.html
Copyright © 2020-2023  润新知