IO 拷贝 阻塞 父子进程

1.使用两个进程完成两个文件的拷贝,父进程拷贝前一半内容,子进程拷贝后一半内容,并且父进程要阻塞回收子进程资源

#include <myhead.h>

int main(int argc, const char *argv[])
{
    if(3!=argc)
    {
        printf("The number of arguments error!\n");
        printf("Usage:./a.out srcfileName desfileName\n");
        return -1;
    }

    pid_t pid;
    FILE *srcfp;
    FILE *dstfp;
    if(NULL==(srcfp=fopen(argv[1],"r")))
    {
        perror("fopen error");
        return -1;
    }
    
    if(NULL==(dstfp=fopen(argv[2],"w+")))
    {
        perror("fopen error");
        return -1;
    }
    int count = 0;
    char buf;
    while(fread(&buf,1,1,srcfp)>0)
    {
        count++;
    }
    int halfCount = count/2;
    fseek(srcfp,0,SEEK_SET);

    pid = fork(); //创建子进程
    if(pid<0)
    {
        perror("fork error");
        return -1;
    }else if(pid==0)
    {
        int countChild=0;
        int bufChild=0;

        fseek(srcfp,halfCount,SEEK_SET);
        fseek(dstfp,halfCount,SEEK_SET);
        printf("\n****这是子进程****\n");

        while(EOF!=(bufChild=fgetc(srcfp))&&countChild<(count-halfCount))
        {
            printf("%c",bufChild);
            fputc(bufChild,dstfp);
            countChild++;
        }
        fclose(dstfp);
        exit(EXIT_SUCCESS);
    }else
    {
        wait(NULL);
        int countFather=0;
        char bufFather=0;

        fseek(srcfp,0,SEEK_SET);
        fseek(dstfp,0,SEEK_SET);
        printf("\n****这是父进程****\n");

        while(EOF!=(bufFather=fgetc(srcfp))&&countFather<halfCount)
        {
            printf("%c",bufFather);
            fputc(bufFather,dstfp);
            countFather++;
        }
        fclose(dstfp);
        putchar(10);
    }
    return 0;
}

 2.使用三个进程完成两个文件的拷贝,父进程拷贝前三分之一,子进程1拷贝中间三分之一,子进程2拷贝后三分之一,父进程要阻塞回收所有子进程资源

#include<myhead.h>
int main(int argc, const char *argv[])
{
    //判断输入是否合法,如果不合法则输出正确格式并且结束程序
    if(3!=argc){
        printf("The number of arguments error!\n");
        printf("Usage:./a.out srcfileName dstfileName\n");
        return -1;
    }
 
    //创建一个进程号类型的变量
    pid_t pid;
 
    //创建指向被复制文件的文件指针
    FILE *srcfp;
    //创建指向目标文件的文件指针
    FILE *dstfp;
    //打开被复制文件并且判断是否成功打开,失败则输出错误码并结束程序
    if(NULL==(srcfp = fopen(argv[1],"r"))){
        perror("fopen error");
        return -1;
    }
    //打开目标文件并且判断是否成功打开,失败则输出错误码并结束程序
    if(NULL==(dstfp = fopen(argv[2],"w+"))){
        perror("fopen error");
        return -1;
    }
 
    //文件内容计数
    int count = 0;
    char buf;
    //每次只读取一字节,读取到就计数加1,没读取到内容就说明结束.
    while(fread(&buf,1,1,srcfp)>0){
        count++;
    }
    int oneThirdCount = count/3;
    int twoThirdCount = count*2/3;
    //计数结束之后要将指针归位
    fseek(srcfp,0,SEEK_SET);
 
    //创建子进程
    pid = fork();
 
    //判断逻辑
    if(pid < 0){
        //如果pid小于0说明子进程创建失败,输出错误信息并结束程序
        perror("fork error");
        return -1;
    }else if(0 == pid){
 
        //子进程中再次创建一个子进程,定义孙子进程的进程号变量
        pid_t gpid;
        //在这个程序中,这是孙子进程
        gpid = fork();
 
        //判断逻辑
        if(gpid < 0){
            //如果pid小于0说明子进程创建失败,输出错误信息并结束程序
            perror("fork error");
            return -1;
        }else if(0 == gpid){
 
            //pid为0且gpid为0说明这是子进程的子进程,称之为孙子进程
 
            //定义一个变量记录已经写入了多少个字符
            int countGrandChild = 0;
            //定义一个在孙子进程中使用的搬运工
            int bufGrandChild = 0;
 
            //重定向到文件开头往后twoThirdCount位置
            //根据子进程的循环条件可知,写到了twoThirdCount位置的前一个字符位置,
            //所以应该重定向到twoThirdCount位置
            fseek(srcfp,twoThirdCount,SEEK_SET);
            fseek(dstfp,twoThirdCount,SEEK_SET);
            printf("\n*****这是孙子进程*****\n");
 
            //当读取到文件结尾或者读取计数计完剩下的值后结束
            //这里主要两个判断条件应该是同时满足的,写哪一个都行
            //都写上双保险
            while(EOF!=(bufGrandChild=fgetc(srcfp))&&countGrandChild<(count-twoThirdCount)){
                //在终端中输出,有一个可视的过程
                printf("%c",bufGrandChild);
                fputc(bufGrandChild,dstfp);
                //写入字符计数
                countGrandChild++;
            }
 
            //关闭文件
            fclose(dstfp);
            printf("\n*****这是孙子进程*****\n");
 
            //孙子进程结束,返回结束信号,让其父,也就是这个程序中的子进程进行收尸
            exit(EXIT_SUCCESS);
        }else{
 
            //pid等于0,但是gpid>0,说明当前正运行在子进程中
            //挂起等待孙子进程结束后给他收尸并且确保程序的运行顺序
            wait(NULL);
 
            //定义一个变量记录已经写入了多少个字符
            int countChild = 0;
            //定义一个在子进程中使用的搬运工
            int bufChild = 0;
 
            //将文件指针重定向到文件oneThirdCount位置,由父进程的判断条件可知
            //父进程写到oneThirdCount的前一个字符位置,所以子进程要从oneThirdCount位置开始
            //子进程只写文件的中间1/3部分
            fseek(srcfp,oneThirdCount,SEEK_SET);
            fseek(dstfp,oneThirdCount,SEEK_SET);
            printf("\n*****这是子进程*****\n");
 
            //当读取到结束或者写入的字符数超过中间1/3时停止,在这个进程中,起作用的主要
            //是字符数计数的条件,因为只写中间1/3
            while(EOF!=(bufChild=fgetc(srcfp))&&countChild<(twoThirdCount-oneThirdCount)){
                //在终端中输出,有一个可视的过程
                printf("%c",bufChild);
                fputc(bufChild,dstfp);
                //写入字符计数
                countChild++;
            }
 
            //关闭文件
            fclose(dstfp);
            printf("\n*****这是子进程*****\n");
 
            //子进程结束,返回结束信号
            exit(EXIT_SUCCESS);    
        }
    }else{
 
        //pid等于0,说明当前正运行在父进程中
        //挂起等待子进程的结束,确保父进程能够活到给子进程收尸
        //并且保证程序执行的先后顺序
        wait(NULL);
 
        //定义一个变量记录已经写入了多少个字符
        int countFather = 0;
        //定义一个在父进程中使用的搬运工
        char bufFather = 0;
 
        //将文件指针重定向到文件开头
        //父进程只写文件的前1/3部分
        fseek(srcfp,0,SEEK_SET);
        fseek(dstfp,0,SEEK_SET);    
        printf("\n*****这是父进程*****\n");
 
        //当读取到结束或者写入的字符数超过1/3时停止,在这个进程中,起作用的主要
        //是字符数计数的条件,因为只写前1/3
        while(EOF!=(bufFather=fgetc(srcfp))&&countFather<oneThirdCount){
            printf("%c",bufFather);
            fputc(bufFather,dstfp);
            //计数自增
            countFather++;
        }
        //关闭文件
        fclose(dstfp);    
        printf("\n*****这是父进程*****\n");
    }
 
    //printf("被复制文件%s和目标文件%s打开成功\n",argv[1],argv[2]);
    //测试
    //printf("count = %d\n",count);
 
    return 0;
}

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值