使用父子两个进程拷贝同一个文件,父进程拷贝前一半,子进程拷贝后一半。

#include <head.h>

// 父子进程在宏观上同时执行,微观上实际是时间片轮询串行。

//两个进程同时调用同一个拷贝函数进行拷贝

int get_file_len(const char *src){

    // 每个文件进程控制块中都有一份文件描述符表

    // (可以把它看成是一个数组,里面的元素是指向file结构体指针类型),

    // 这个数组的下标就是文件描述符。

    // 在源代码中,一般用fd作为文件描述符的标识。

    int fd,len;

    if((fd = open(src,O_RDONLY))==-1)

        PRINT_ERR("open src error");

    len = lseek(fd,0,SEEK_END);

    //将光标定位到最后,返回总字节数给len

    //这时光标在结尾,所以要关闭文件

    close(fd);

    return len;

}

int init_dest_file(const char *dest){

    //初始化目标文件,保证拷贝文件时目标文件是存在的

    //有则清空写入,无则创建给读写权限

    int fd;

    if((fd = open(dest,O_WRONLY|O_TRUNC|O_CREAT,0666))==-1)

        PRINT_ERR("open dest error");

    close(fd);

    return 0;

}

int copy_file(const char *src,const char *dest,int start, int len){

    int fd1,fd2,ret,count=0;

    char buf[128]={0};

    //如果是先打开文件,在fork进程此时2个进程同时用一个光标

    //而如果先fork在打开是2个进程分别打开他们对应各自的文件,

    //2个进程用他们各自的光标,这个函数分别被2个进程同时调用

    //打开两个文件

    if((fd1 = open(src,O_RDONLY))==-1)

        PRINT_ERR("open src error");

    if((fd2 = open(dest,O_WRONLY))==-1)

        PRINT_ERR("open dest error");

    //定位2个进程的光标要拷贝的开始位置

    lseek(fd1,start,SEEK_SET);

    lseek(fd2,start,SEEK_SET);

    //循环拷贝

    while(1){

        //先读fd1的数据到字符串内

        ret = read(fd1,buf,sizeof(buf));

        count+=ret;//记录拷贝的字节数

        //再将字符串的内容写入fd2中

        //如果字符串读取字符数量不满128执行下面

        //判断buf是否读满

        //当子进程先复制时,复制的是前半部分,最后一次ret读取的是128,count是128的倍数

        //这样读取最后一次会超过len/2的位置,而我们值想要len/2之前的字符串

        if(count >= len){

            write(fd2, buf, ret-(count-len));

            break;//循环停止的条件count >= len

        }

        //如果字符串满拷贝执行下面

        write(fd2,buf,ret);

    }

}

// ./a.out srcfile destfile

int main(int argc, const char *argv[])

{

    int len = 0;

    pid_t pid;

    //检查参数

    if(argc != 3){

        fprintf(stderr,"input error,try again\n");

        fprintf(stderr,"usage:./a.out srcfile destfile\n");

        return -1;

    }

    //获取文件的大小,为了做光标定位,父进程定位1/2长度位置

    len = get_file_len(argv[1]);

    //初始化目标文件,保证拷贝文件时目标文件是存在的

    //有则清空写入,无则创建给读写权限

    init_dest_file(argv[2]);

    //fork进程

    pid = fork();//每fork一次就创建一个进程

    //pid_t就是一个short类型变量,pid就是一个short的数字而已,

    // 实际表示的是内核中的进程表的索引。

    //先把进程if框架写出

    if(pid == -1){//-1为创建失败

        PRINT_ERR("fork error");//有置位,报错显示

    }else if(pid == 0){//pid为0时 此时为子进程操作

        //子进程光标 从0开始拷贝移动 len/2的长度

        copy_file(argv[1],argv[2],0,len/2);

    }else{//pid为其他值时为父进程操作,此时pid是子进程的值

    //当fork后会有2个进程同时在运行这一套程序,

    //满足pid为0的说明是子进程在运行这个程序

    //满足pid为其他值的说明是父进程在运行这个程序

        //父进程光标 从len/2开始拷贝移动 len-len/2的长度

        copy_file(argv[1],argv[2],len/2,len-len/2);

        wait(NULL);

        //父进程直到子进程运行结束后回收子进程,防止孤儿进程

    }

    return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值