Linux&C语言简单实现双/3进程拷贝-文件IO实现

1. 基于C语言实现,文件IO练习

2.代码实现

2.1(命令行指定)使用父子进程拷贝同一个文件,父进程拷贝前半部分,子进程拷贝后半部分

#include <stdio.h> // Shift  +  Alt  + F     实现代码的对齐;
/* fork函数的头文件*/
#include <sys/types.h>
#include <unistd.h>
/* open函数的头文件---文件IO*/
//#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
/*wait函数的头文件*/
#include <wait.h>

/*exit*/
#include <stdlib.h>

/* lseek函数的头文件---文件IO*/
//#include <sys/types.h>
//#include <unistd.h>

/*计算要拷贝文件字符个数*/
int get_src_file_len(const char *srcfile,const char * destfile)
{
    int sfd,dfd;
    int len=0;
    //打开目标要拷贝的文件
    if((sfd = open(srcfile,O_RDONLY))==-1){//只读
        printf("open srcfile error");
    }
    //打开存放拷贝的文件
    if((dfd = open(destfile,O_RDWR|O_CREAT|O_TRUNC,0664))==-1){
                            //读写| 创建文件| 清空文件
        printf("open destfile error");
    }
    //读取目标要拷贝的文件的字节数
    len = lseek(sfd,0,SEEK_END);

    close(sfd);//关闭文件
    close(dfd);
    return len;
}
/*父子进程拷贝文件*/
int copy_file(const char *srcfile,const char * destfile,int start,int len)
{
    int sfd,dfd;
    char buf[10] = {0};
    int ret=0;
    //记录已经读取字节数
    int i = 0;
    //打开目标要拷贝的文件
    if((sfd = open(srcfile,O_RDONLY))==-1){//只读
        printf("open srcfile error");
    }
    //打开存放拷贝的文件
    if((dfd = open(destfile,O_RDWR))==-1){//读写
        printf("open destfile error");
    }
    //光标从头开始,移动start
    lseek(sfd,start,SEEK_SET);
    lseek(dfd,start,SEEK_SET);

    while(1){
        ret = read(sfd,buf,sizeof(buf));

        i+=ret;//记录已经读取字节数
        //结尾||读多了
        if(ret==0 || i>len) {
           write(dfd,buf,ret-(i-len)); 
           break;
        }  
        write(dfd,buf,ret); 
    }
    close(sfd);
    close(dfd);
    return 0;
}
int main(int argc,const char * argv[])
{
    //检测命令行 3个参数
    if(argc != 3){
        fprintf(stderr,"input error,try again\n");
        fprintf(stderr,"usage:./a.out srcfile,destfile\n");
        return -1;
    }
    /*计算要拷贝文件字符个数*/
    int len = get_src_file_len(argv[1],argv[2]);
    printf("len = %d\n",len);
    //新建子进程
    pid_t pid;
    pid = fork();

    if(pid < 0){
       printf("fork error");
    }else if(pid == 0){
        printf("child start = %d,len=%d\n",0,len/2);
        //进程写前半部分
        copy_file(argv[1],argv[2],0,len/2);
        exit(EXIT_SUCCESS);//退出进程的时候会刷新缓冲区
    }else{
        printf("parent start = %d,len=%d\n",len/2,len-len/2);
        //进程写后半部分
        copy_file(argv[1],argv[2],len/2,(len-len/2));
        wait(NULL);//阻塞等待回收子进程的资源
    }
    return 0;
}

执行结果

在这里插入图片描述

2.2(非命令行指定)使用父子进程拷贝同一个文件,父进程拷贝前半部分,子进程拷贝后半部分

#include <stdio.h> // Shift  +  Alt  + F     实现代码的对齐;
/* fork函数的头文件*/
#include <sys/types.h>
#include <unistd.h>

/* open函数的头文件---文件IO*/
//#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
/*wait函数的头文件*/
#include <wait.h>

/* lseek函数的头文件---文件IO*/
//#include <sys/types.h>
//#include <unistd.h>

/*父子进程拷贝文件*/
int copy_2(int fd, int df)
{
    int ret, ret0, ret1;
    char buy[1];
    //读取目标要拷贝的文件的字节数
    ret1 = lseek(fd, 0, SEEK_END) / 2;
    //记录已经读取字节数
    int i = 0;
    /*进程写前/后半部分*/
    //进程写前半部分
    // SEEK_END从结尾开始 ;lseek功能:修改文件中光标的位置,
    //返回值:成功返回光标当前位置到开头的字节数
    if ((ret0 = lseek(df, 0, SEEK_END)) <= 0) //还没有进程执行
    {
        lseek(fd, 0, SEEK_SET);
        while ((ret = read(fd, buy, sizeof(buy))) > 0 && i < ret1)
        {
            write(df, buy, ret);
            i += ret;
        }
        printf("前半部分\n");
    }
    //进程写后半部分
    else if ((ret0 = lseek(df, 0, SEEK_END)) > 0) //进程已经执行
    {
        // SEEK_SET从头开始
        lseek(fd, ret0, SEEK_SET);
        while ((ret = read(fd, buy, sizeof(buy))) > 0)
        {
            write(df, buy, ret);
        }
        printf("后半部分\n");
    }
    return 0;
}

int main(int argc, char const *argv[])
{
    int fd, df;

    //先打开目标,要拷贝的文件
    if ((fd = open("./01.txt", O_RDONLY)) == -1)
        printf("open src error\n");
    //打开拷贝存放的文件                  //a+
    if ((df = open("./03-03作业-存放拷贝.txt", O_RDWR | O_APPEND | O_CREAT, 0664)) == -1)
        printf("open src error\n");

    pid_t pid;

    char s1[50] = {0};

    //创建子进程
    pid = fork(); // fork成功父进程收到子进程的PID,子进程收到0.

    if (pid < 0)
    {
        printf("fork error\n");
    }

    else if (pid == 0)
    {
        printf("\n");
        printf("这是子进程\n");
        printf("\n");
        copy_2(fd, df);
    }
    else
    {
        printf("这是父进程\n");
        printf("\n");
        copy_2(fd, df);
        wait(NULL); //阻塞等待回收子进程的资源
    }

    return 0;
}

执行结果

在这里插入图片描述

2.3 (命令行指定)使用三个进程拷贝同一个文件,每个进程拷贝文件的1/3

#include <stdio.h> // Shift  +  Alt  + F     实现代码的对齐;
/* fork函数的头文件*/
#include <sys/types.h>
#include <unistd.h>
/* open函数的头文件---文件IO*/
//#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
/*wait函数的头文件*/
#include <wait.h>

/*exit*/
#include <stdlib.h>

/* lseek函数的头文件---文件IO*/
//#include <sys/types.h>
//#include <unistd.h>


/*计算要拷贝文件字符个数*/
int get_src_file_len(const char *srcfile,const char * destfile)
{
    int sfd,dfd;
    int len=0;
    //打开目标要拷贝的文件
    if((sfd = open(srcfile,O_RDONLY))==-1){//只读
        printf("open srcfile error");
    }
    //打开存放拷贝的文件
    if((dfd = open(destfile,O_RDWR|O_CREAT|O_TRUNC,0664))==-1){
                            //读写| 创建文件| 清空文件
        printf("open destfile error");
    }
    //读取目标要拷贝的文件的字节数
    len = lseek(sfd,0,SEEK_END);

    close(sfd);//关闭文件
    close(dfd);
    return len;
}
/*父子进程拷贝文件*/
int copy_file(const char *srcfile,const char * destfile,int start,int len)
{
    int sfd,dfd;
    char buf[10] = {0};
    int ret=0;
    //记录已经读取字节数
    int i = 0;
    //打开目标要拷贝的文件
    if((sfd = open(srcfile,O_RDONLY))==-1){//只读
        printf("open srcfile error");
    }
    //打开存放拷贝的文件
    if((dfd = open(destfile,O_RDWR))==-1){//读写
        printf("open destfile error");
    }
    //光标从头开始,移动start
    lseek(sfd,start,SEEK_SET);
    lseek(dfd,start,SEEK_SET);

    while(1){
        ret = read(sfd,buf,sizeof(buf));

        i+=ret;//记录已经读取字节数
        //结尾||读多了
        if(ret==0 || i>len) {
           write(dfd,buf,ret-(i-len)); 
           break;
        }  
        write(dfd,buf,ret); 
    }
    close(sfd);
    close(dfd);
    return 0;
}

int main(int argc,const char * argv[])
{
    //检测命令行 3个参数
    if(argc != 3){
        fprintf(stderr,"input error,try again\n");
        fprintf(stderr,"usage:./a.out srcfile,destfile\n");
        return -1;
    }
    /*计算要拷贝文件字符个数*/
    int len= get_src_file_len(argv[1],argv[2]);
    printf("len = %d\n",len);
    //新建子进程
    pid_t pid,pid1;
    pid = fork();
    if(pid < 0){
        printf("fork error");
    }else if(pid == 0){
        printf("child1 start = %d,len=%d\n",0,len/3);
        //进程写前1/3部分
        copy_file(argv[1],argv[2],0,len/3);
        exit(EXIT_SUCCESS);
    }else{
        //新建子进程
        pid1=fork();
        if(pid1<0){
            printf("fork pid1 process error");
        }else if(pid1 == 0){
            printf("child2 start = %d,len=%d\n",len/3,(len/3)*2);
            //进程写中1/3部分
            copy_file(argv[1],argv[2],len/3,(len/3)*2);
            exit(EXIT_SUCCESS);
        }
        //进程写最后半部分
        printf("parent start = %d,len=%d\n",(len/3)*2,len-(len/3)*2);
        copy_file(argv[1],argv[2],(len/3)*2,len-(len/3)*2);
        wait(NULL); //阻塞回收子进程,但是回收那个子进程的资源不确定,只要回收一个就会退出
        wait(NULL); //阻塞回收子进程,但是回收那个子进程的资源不确定,只要回收一个就会退出
    }
    return 0;
}
执行结果

在这里插入图片描述

2.4 (非命令行指定)使用三个进程拷贝同一个文件,每个进程拷贝文件的1/3

#include <stdio.h> // Shift  +  Alt  + F     实现代码的对齐;
/* fork函数的头文件*/
#include <sys/types.h>
#include <unistd.h>

/* open函数的头文件---文件IO*/
//#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
/*wait函数的头文件*/
#include <wait.h>

/* lseek函数的头文件---文件IO*/
//#include <sys/types.h>
//#include <unistd.h>

/*3进程拷贝文件*/
int copy_3(int fd, int df)
{
    int ret, ret0, ret1;
    char buy[1];
    //读取目标要拷贝的文件的字节数
    ret1 = lseek(fd, 0, SEEK_END) / 3;
    //记录已经读取字节数
    int i = 0;
    /*进程写前/中/后部分*/
    //进程写前部分
    // SEEK_END从结尾开始 ;lseek功能:修改文件中光标的位置,
    //返回值:成功返回光标当前位置到开头的字节数
    if ((ret0 = lseek(df, 0, SEEK_END)) <= 0) //还没有进程执行
    {
        lseek(fd, 0, SEEK_SET);
        while ((ret = read(fd, buy, sizeof(buy))) > 0 && i < ret1)
        {
            write(df, buy, ret);
            i += ret;
        }
        printf("前部分\n");
    }
    //进程写中部分
    else if ((ret0 = lseek(df, 0, SEEK_END))==ret1) //进程已经执行
    {
        // SEEK_SET从头开始
        lseek(fd, ret0, SEEK_SET);
        while ((ret = read(fd, buy, sizeof(buy))) > 0 && i < ret1)
        {
            write(df, buy, ret);
            i += ret;
        }
        printf("中部分\n");
    }
    //进程写后部分
    else //进程已经执行
    {
        ret0 = lseek(df, 0, SEEK_END);
        // SEEK_SET从头开始
        lseek(fd, ret0, SEEK_SET);
        while ((ret = read(fd, buy, sizeof(buy))) > 0)
        {
            write(df, buy, ret);
        }
        printf("后部分\n");
    }
    return 0;
}

int main(int argc, char const *argv[])
{
    int fd, df;

    //先打开目标,要拷贝的文件
    if ((fd = open("./01.txt", O_RDONLY)) == -1)
        printf("open src error\n");
    //打开拷贝存放的文件                  //a+
    if ((df = open("./04-04作业-存放3进程拷贝.txt", O_RDWR | O_APPEND | O_CREAT, 0664)) == -1)
        printf("open src error\n");

    pid_t pid;

    char s1[50] = {0};

    //创建子进程
    pid = fork(); // fork成功父进程收到子进程的PID,子进程收到0.

    if (pid < 0)
    {
        printf("fork error\n");
    }

    else if (pid == 0)
    {
        printf("\n");
        printf("这是子1进程\n");
        printf("\n");
        copy_3(fd, df);
    }
    else
    {
        //父进程再创建子进程
        pid_t pid1;
        pid1 = fork();
        if (pid1 < 0)
        {
            printf("fork error\n");
        }

        else if (pid1 == 0)
        {
            printf("\n");
            printf("这是子2进程\n");
            printf("\n");
            copy_3(fd, df);
        }
        else
        {
            printf("这是父进程\n");
            printf("\n");
            copy_3(fd, df);
            wait(NULL); //阻塞等待回收子进程的资源
            wait(NULL); //阻塞等待回收子进程的资源
        }
    }
        return 0;
    }

执行结果

在这里插入图片描述

6. 非原创

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值