Linux 多线程文件复制

 

参考了朋友的设计思想,重新编写了代码实现文件的多线程复制

 

fcp.h代码:


#ifndef __FCP_H
#define __FCP_H
#define MAX 125
//define read block struct
typedef struct _page
{
    char fin[MAX];
    char fout[MAX];
    long offset;
    long size;
    int id;
}__attribute__((packed)) page;
int multi_copy();
#endif




fcp.c  代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include "fcp.h"
#define THREAD_SIZE 5
#define UNIT 16*1024
//get file size
int fsize(char *filename)
{
   struct stat st;
   memset(&st,0,sizeof(st));
   stat(filename,&st);
   return st.st_size;
}
int thread_copy(void *arg)
{
    page *p1=(page *)arg;
    char buf[UNIT];
    memset(buf,0,sizeof(buf));
    FILE *in=fopen(p1->fin,"r");
    FILE *out=fopen(p1->fout,"rb+");
    if(out==NULL||NULL==in)
    {
        fprintf(stderr,"source/target file is null\n");
        return -1;
    }
    printf("Thread id=%ld,id=%d\n",pthread_self(),p1->id);
    printf("\tp1->id=%d,p1->offset=%ld,p1->size=%ld\n",p1->id,p1->offset,p1->size);
    fseek(in,p1->offset,SEEK_SET);
    fseek(out,p1->offset,SEEK_SET);
    long size=p1->size;
    int len,writen,left;
    while(size>0)
    {
        len=size;
        if(len>sizeof(buf))
        {
            len=sizeof(buf);
        }
        len=fread(buf,1,len,in);
        if(len<0){fprintf(stderr,"read src file error\n");break;}
        size-=len;
        writen=0;
        left=len;
        while(left>0)
        {
            len=fwrite(buf,1,left,out);
            if(len<0){fprintf(stderr," write target file error\n");break;}
            writen+=len;
            left-=len;
        }
    }
    fclose(in);
    fclose(out);
    printf("********Thread %ld ,id = %d,exit\n",pthread_self(),p1->id,writen);
    pthread_exit(NULL);
    return 0;
}
int multi_copy(char *src,char *dest)
{
    if(0!=access(src,F_OK)){fprintf(stderr,"file is not exists\n");return -1;}
    if(0==access(dest,F_OK)){remove(dest);}
    size_t size=fsize(src);
    int fd=open(dest,O_RDWR|O_CREAT,0666);
    if(fd<0)
    {
        close(dest);
        fprintf(stderr," file open error\n");
        return -1;
    }
    if(fallocate(fd,0,0,size)!=0)
    {
        close(fd);
        fprintf(stderr,"create file error\n");
        return -1;
    }
    close(fd);
    int thread_size=THREAD_SIZE;
    int i;
    if(size<thread_size){thread_size=1;}
    pthread_t works[thread_size];
    page *p=(page *)malloc(sizeof(*p)*thread_size);
    if(!p){fprintf(stderr," malloc memory for page error\n");return -1;}
    long per_size=size/thread_size;
    printf("  Thread size =%d,Percent size =%d\n",thread_size,per_size);
    long offset=0;
    for(i=0;i<thread_size;i++)
    {
        strncpy(p[i].fin,src,strlen(src));
        strncpy(p[i].fout,dest,strlen(dest));
        p[i].offset=offset;
        p[i].id=i;
        if(i==(thread_size-1))
        {
            p[i].size=size-offset;
        }
        else
        {
            p[i].size=per_size;
        }
        offset+=per_size;
    }
    for(i=0;i<thread_size;i++)
    {
         pthread_create(&works[i],NULL,(void *)&thread_copy,(void *)&p[i]);
    }
    for(i=0;i<thread_size;i++)
    {
        pthread_join(works[i],NULL);
    }
    if(p!=NULL)
    {
        free(p);
        p=NULL;
    }
    return 0;
}
void usage()
{
    printf("usage: fcp sourcefile targetfile\n");
}
int main(int argc,char *args[])
{
    if(argc<3)
    {
        usage();
        return -1;
    }
    char *fin=args[1];
    char *fout=args[2];
    printf("\n*******%s  size =%ld\n",fin,fsize(fin));
    multi_copy(fin,fout);
    return 0;
}

备注:参考老汪的设计思路

你可以使用 Linux shell 的 `rsync` 命令来实现多线程复制文件的脚本。`rsync` 是一个功能强大的文件复制工具,支持多线程复制和增量复制。 以下是一个简单的示例脚本,可以在 Linux shell 中运行: ```shell #!/bin/bash # 源文件目录 source_dir="/path/to/source" # 目标文件目录 target_dir="/path/to/target" # 并发线程数 threads=4 # 复制文件 rsync -r --progress --human-readable --stats --partial --info=progress2 --inplace --files-from=<(cd $source_dir && find . -type f) $source_dir $target_dir --parallel=$threads ``` 在脚本中,你需要修改 `source_dir` 和 `target_dir` 变量为你实际的源文件目录和目标文件目录。同时,你可以根据需要调整并发线程数 `threads`。 脚本中使用了 `rsync` 命令的多个参数,具体含义如下: - `-r`:递归复制文件夹及其内容。 - `--progress`:显示复制进度。 - `--human-readable`:以人类可读的方式显示进度。 - `--stats`:显示复制统计信息。 - `--partial`:支持断点续传。 - `--info=progress2`:显示更详细的进度信息。 - `--inplace`:直接在目标位置进行修改,而不是创建临时文件。 - `--files-from=<(cd $source_dir && find . -type f)`:从源文件目录中的文件列表中复制文件。 - `$source_dir` 和 `$target_dir`:源文件目录和目标文件目录。 - `--parallel=$threads`:指定并发线程数。 请注意,`rsync` 命令在复制过程中会自动检测已复制文件,只复制有变化的部分,以实现增量复制。 希望这个示例能帮助到你!如果有任何问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值