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\n",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("子进程开始\n");
        printf("子进程读取大小:%ld\n",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\n");
                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 \n");
                break;
            }
        }
        exit(1); //退出子进程
    }
    else //父进程
    {
        waitpid(pid, &status, 0);//等待子进程执行完在执行
        printf("父进程开始\n");
        printf("父进程读取大小:%ld\n",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\n");
                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 \n");    
        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 = '\0';
    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);//在文件的末尾先添加一个 '\0' 结尾符,确定写文件的大小

    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;
}

猜你喜欢

转载自www.cnblogs.com/electronic/p/10932631.html