使用多线程分片断拷贝一个普通文件

时间:2022-06-24 10:07:00

程序的执行方式为:

./a.out n src dst (其中n代表线程数量)
/************************************************************************* * File Name: copyfile.c * Author: lixiaogang * Function: 线程拷贝文件 * Mail: 2412799512@qq.com * Created Time: 2017年06月12日 星期一 21时32分08秒 ************************************************************************/

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<pthread.h>
#include<string.h>
#include<unistd.h>

typedef struct 
{
    char src_file[1024];
    char dst_file[1024];
    int start;
    int length;
}Args;

/* 封装出错打印函数 */
void sys_err(const char *ptr,int num)
{
    perror(ptr);
    exit(num);
}

void *pthreadFunc(void *args)
{
    Args *arg = (Args *)args;
    int src_fd = open(arg->src_file,O_RDONLY);
    int dst_fd = open(arg->dst_file,O_WRONLY);

    lseek(src_fd,arg->start,SEEK_SET);
    lseek(dst_fd,arg->start,SEEK_SET);

    char buf[1024];
    while(arg->length > 0)
    {
        memset(buf,0x00,sizeof(buf));
        int len = read(src_fd,buf,arg->length);
        if(len < 0)
        {
            break;
        }
        /* 向文件写入真实读到的字节数 */
        write(dst_fd,buf,len);
        arg->length -= len;
    }

    free(arg);
    close(src_fd);
    close(dst_fd);
}

/* 文件拷贝实现 */
void copyFile(int num,const char *src,const char *dst)
{
    struct stat st;
    int i;
    int flag = stat(src,&st);
    if(flag < 0)
    {
        sys_err("stat",-1);
    }

    /* num个线程,平均每个线程负责拷贝的数据块大小*/
    int averageSize = st.st_size / num;
    /* num线程个数不确定,所以把余下的数据块给最后线程*/
    int lastSize = st.st_size % num; 
    int dstfd = open(dst,O_CREAT,0777);
    if(dstfd < 0)
    {
        sys_err("open",-2);
    }
    /*为目标文件分配源文件大小的内存空间*/
    ftruncate(dstfd,st.st_size);
    close(dstfd);

    pthread_t *tid = (pthread_t *)malloc(sizeof(pthread_t) * num);
    if(NULL == tid)
    {
        sys_err("pthread_t malloc",-3);
    }
    for(i = 0;i < num; ++i)
    {
        Args *arg = (Args *)malloc(sizeof(Args));
        strcpy(arg->src_file,src);
        strcpy(arg->dst_file,dst);
        arg->start = averageSize * i;
        /* 判断是否为最后的一个线程,若是,则其拷贝数据块+lastsSize */
        if(i == num - 1)
            arg->length = averageSize + lastSize;
        else
            arg->length = averageSize;

        /* 创建线程 */
        pthread_create(tid + i,NULL,pthreadFunc,(void *)arg);
        /* 回收线程所占用的内存资源 */
    }
    for(i = 0; i< num; ++i)
    {
        pthread_join(tid[i],NULL);
    }

    free(tid);
}


int main(int argc,char *argv[])
{
    /* ./a.out n src dst */
    if(argc != 4)
    {
        printf("Usage: filename num src dst.\n");
        return -1;
    }

    const char *src = argv[2];
    const char *dst = argv[3];
    int num = atoi(argv[1]);
    /*拷贝文件*/
    copyFile(num,src,dst);

    return 0;
}