zoukankan      html  css  js  c++  java
  • Linux 父子进程实现复制文件内容到另一个文件内

    1. 子进程先拷贝前一半 ,父进程一直阻塞到子进程拷贝完再拷贝后一半

    /* 子进程先拷贝前一半文件,父进程先阻塞等待子进程拷贝完前一半内容,
     * 然后父进程在拷贝,后一半内容
     * */
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <sys/wait.h>
    
    //pid_t fork(void);
    int main(int argc, const char *argv[])
    {
        int fd_r, fd_w;
        char buf[5] = {0};
        int status;
        fd_r = open(argv[1],O_RDONLY); //打开读取内容的文件
        if(fd_r < 0)
        {    perror("read file  open fail : ");    return -1;    }
    
        fd_w = open(argv[2],O_WRONLY | O_APPEND,0666); //打开要写入的文件
        if(fd_w < 0)
        {    perror("write file  open fail : ");close(fd_r);    return -1;    }
    
        off_t fileSize = 0;//文件大小
        fileSize = lseek(fd_r,0,SEEK_END) - lseek(fd_r,0,SEEK_SET);//读取源文件有多少个字符:w
        printf("源文件大小:%ld
    ",fileSize);
        off_t c_read_size;//子进程,读取文件的大小
        c_read_size = fileSize / 2;
    
        off_t f_read_size;//父进程,读取文件的大小
        f_read_size = fileSize - c_read_size;
    
    
    #if 1
        pid_t pid ;
        pid = fork();
        if(pid == -1)  {perror("pid fail : ");    exit(1);}
    
        else if(pid == 0)//子进程
        {
            printf("子进程开始
    ");
            printf("子进程读取大小:%ld
    ",c_read_size);
    
            ssize_t size_cnt = 0;//记录读取的个数
            ssize_t temp_size = 0;//临时读取记录
            while(1) //循环读,读取到中间位置
            {
                temp_size = read(fd_r,buf,1);
                if(temp_size <= 0)//没有读取到数据,或者读取出错
                {
                    printf("child read fail or end
    ");
                    break;
                }
                ssize_t tt =0; //子进程写入失败
                tt = write(fd_w,buf,1); //读取到 数据写入文件
                if(tt ==-1)
                {    perror("child write file fail :");    break;    }
    
                size_cnt = size_cnt + temp_size;
                if(size_cnt >= c_read_size) //读取到该读的数据
                {
                    printf("child write file end 
    ");
                    break;
                }
            }
            exit(1); //退出子进程
        }
        else //父进程
        {
            waitpid(pid, &status, 0);//等待子进程执行完在执行
            printf("父进程开始
    ");
            printf("父进程读取大小:%ld
    ",f_read_size);
            lseek(fd_r,-f_read_size,SEEK_END);//相对文件末尾向移动到,子进程读取的位置
        
            while(1)//开始读取数据
            {
                ssize_t f_read_size;
                f_read_size = read(fd_r,buf,1);
                if(f_read_size <= 0)//读取到末尾返回值为 0 
                {
                    printf("father read file end
    ");
                    break;
                }
                ssize_t t =0; //父进程写入失败
                t = write(fd_w,buf,1);
                if(t ==-1)
                {
                    perror("father write file fail : ");
                    break;
                }
            }
            printf("father write file end 
    ");    
            exit(1);
        }
    #endif
        close(fd_r);
        close(fd_w);
        return 0;
    }

    测试:

         

    2. 父子进程同时拷贝,父进程拷贝前一半,子进程拷贝后一半,写文件的顺序不确定,所以写入后内容会乱

    /* copy文件,父进程先拷贝前一半,子进程拷贝后一半
     * 文件内容可以完整拷贝,写数据时顺序会打乱
     * 父进程写一点,子进程写一点
     * */
    #include <stdio.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <sys/wait.h>
    
    int main(int argc, const char *argv[])
    {
        int fd_r,fd_w;
        off_t size;
        char ch = '';
        pid_t pid;
        char buf[64] = {0};
        ssize_t tmp = 0;
    
        if((fd_r = open(argv[1],O_RDONLY)) == -1)
        {
            perror("fcntlail to open fd_r");
            exit(1);
        }
    
        if((fd_w = open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0666)) == -1) //打开写的文件,没有就创建,有内容就清空,只写方式打开
        {
            close(fd_r);
            perror("fail to open FD_ZEROBASED_w");
            exit(1);
        }
    
        size = lseek(fd_r,0,SEEK_END);
        lseek(fd_w,size    - 1,SEEK_SET);
        write(fd_w,&ch,1);//在文件的末尾先添加一个 '' 结尾符,确定写文件的大小
    
        size /= 2;  //size = size / 2; //文件大小的一半
    
        pid = fork();
        if(pid < 0)
        {
            perror("fail to fork");
            exit(1);
        }
        else if(pid == 0) //子进程拷贝后一半
        {
            lseek(fd_r,size,SEEK_SET);
            lseek(fd_w,size,SEEK_SET);
    
            while((tmp = read(fd_r,buf,sizeof(buf))) > 0)
            {
                write(fd_w,buf,tmp);
            }
    
            close(fd_r);
            close(fd_w);
            exit(0);
        }
        else //父进程,拷贝前一半
        {
            lseek(fd_r,0,SEEK_SET);
            lseek(fd_w,0,SEEK_SET);
            while(1)
            {
                if(size > sizeof(buf))
                {
                    tmp = read(fd_r,buf,sizeof(buf));
                }
                else
                {
                    tmp = read(fd_r,buf,size);
                }
    
                if(tmp <= 0)
                {
                    break;
                }
                size -= tmp;//size = size - tmpfd_w;
    
                write(fd_w,buf,tmp);
            }
            wait(NULL);//等待回收子进程
            close(fd_r);
            close(fd_w);
        }
        return 0;
    }
  • 相关阅读:
    原型模板分享——国外高阶版“大众点评”TripAdvisor
    插画手绘入门教程
    十大用户体验设计失败案例,你知道吗?
    用摹客,轻松管理设计规范!
    摹客“独门绝技”之评论审阅篇
    政务管理系统原型模板分享
    产品经理如何做需求分析?
    python基础知socket编程
    异常处理
    元类,__call__方法和单例模式
  • 原文地址:https://www.cnblogs.com/electronic/p/10932631.html
Copyright © 2011-2022 走看看