一、多线程版本
#include
#include
#include
#include
#include
#include
#define BUFF_SIZE 512
#define PTHREAD_NUMBER 4
typedef struct copy_block{
// char src[BUFF_SIZE]; //source file
// char dest[BUFF_SIZE]; //destnation file
FILE *src; //source file
FILE *dest; //destnation file
long start; //begin position
long segment_size; //aim copy size
int id; //virtual thread id
}__attribute__((packed)) Page;
long file_size(const char *filename);
void pthread_copy(void *task_info);
int multi_copy(const char *dest,const char *src);
int main(int argc,char *argv[])
{
if(argc < 3)
{
fprintf(stderr,"Error params!\n");
return 0;
}
char *src = argv[1];
char *dest = argv[2];
multi_copy(dest,src);
return 0;
}
//get file size
long file_size(const char *filename)
{
struct stat fstat;
memset(&fstat,0,sizeof(fstat));
stat(filename,&fstat);
return fstat.st_size;
}
//thread task
void pthread_copy(void *task_info)
{
//convert void * to Page *
Page *p = (Page *)task_info;
//open file for every thread
// FILE *fin = fopen(p->src,"rb");
// FILE *fout = fopen(p->dest,"ab+");
//seek the stream to the offset
int res_in = fseek(p->src,p->start,SEEK_SET);
int res_out = fseek(p->dest,p->start,SEEK_SET);
char buffer[BUFF_SIZE]; //buffer
long read_size = BUFF_SIZE; //the size for read
long left = p->segment_size; //current left bytes
long read_len = 0; //the size has read
long total_len = 0; //the readed total size
printf("Thread %d begin\t",p->id);
printf("start %ld\t",p->start);
printf("segment_size %ld\n",p->segment_size);
// printf("src %s\t",p->src);
// printf("dest %s\n",p->dest);
//begin copy
while(left > 0)
{
if(left < read_size)
{
read_size = left;
}
//read file
read_len = fread(buffer,sizeof(char),read_size,p->src);
total_len += read_len;
//write file
if(read_len > 0)
{
fwrite(buffer,sizeof(char),read_len,p->dest);
}
//the left size
left -= read_len;
}
pthread_exit(NULL);
}
//create multi thread
int multi_copy(const char *dest,const char *src)
{
//file is exists
int file_exists = access(src,04);//read access
if(file_exists != 0)
{
fprintf(stderr,"file is not exists!\n");
return 1;
}
//file size
long filesize = file_size(src);
//pthread number
int real_pthread_number = PTHREAD_NUMBER;
if(filesize < BUFF_SIZE)
{
real_pthread_number = 1;
}
Page *p = (Page *)malloc(sizeof(*p) * real_pthread_number);
long offset = 0; //offset from file begin
long segment = filesize / real_pthread_number; //the bytes of every thread
long segment_remain = filesize % real_pthread_number; //the left bytes for the last thread
//ctor the task_info
//open file for every thread
FILE *fin = fopen(src,"rb");
FILE *fout = fopen(dest,"wb+");
int i;
for(i = 0;i < real_pthread_number;i++)
{
if((i + 1) == real_pthread_number)
{
p[i].segment_size = segment + segment_remain;
}
else
{
p[i].segment_size = segment;
}
//task file pointer offset
p[i].start = offset;
offset += p[i].segment_size;
//file path
// strncpy(p[i].src,src,strlen(src));
// strncpy(p[i].dest,dest,strlen(dest));
p[i].src = fin;
p[i].dest = fout;
//virtual thread id
p[i].id = i;
}
//create thread
pthread_t work[real_pthread_number];
for(i = 0;i < real_pthread_number;i++)
{
pthread_create(&work[i],NULL,(void *)&pthread_copy,(void *)&p[i]);
}
//wait subthread exit
for(i = 0;i < real_pthread_number;i++)
{
pthread_join(work[i],NULL);
}
//free
if(p != NULL)
{
free(p);
p = NULL;
}
fclose(fin);
fclose(fout);
return 0;
}
在main中以rb打开源文件,wb+打开目标文件
修改结构体存储文件指针
在线程pthread_copy中操作文件指针位置,去除打开文件操作(在线程中以wb+打开文件会将文件截断为0)
在线程调度函数multi_copy中打开文件并在末尾关闭文件
将文件指针赋给每个线程的task_info结构体成员
二、线程锁版本
#include
#include
#include
#include
#include
#include
#define BUFF_SIZE 512
#define PTHREAD_NUMBER 4
typedef struct copy_block{
char src[BUFF_SIZE]; //source file
char dest[BUFF_SIZE]; //destnation file
long start; //begin position
long segment_size; //aim copy size
int id; //virtual thread id
}__attribute__((packed)) Page;
static pthread_mutex_t mut;
long file_size(const char *filename);
void pthread_copy(void *task_info);
int multi_copy(const char *dest,const char *src);
int main(int argc,char *argv[])
{
if(argc < 3)
{
fprintf(stderr,"Error params!\n");
return 0;
}
char *src = argv[1];
char *dest = argv[2];
multi_copy(dest,src);
return 0;
}
//get file size
long file_size(const char *filename)
{
struct stat fstat;
memset(&fstat,0,sizeof(fstat));
stat(filename,&fstat);
return fstat.st_size;
}
//thread task
void pthread_copy(void *task_info)
{
pthread_mutex_lock(&mut);
//convert void * to Page *
Page *p = (Page *)task_info;
//open file for every thread
FILE *fin = fopen(p->src,"rb");
FILE *fout = fopen(p->dest,"rb+");
if(fout == NULL)
{
fprintf(stderr,"Open file %s fail\n",p->dest);
return ;
}
//seek the stream to the offset
int res_in = fseek(fin,p->start,SEEK_SET);
int res_out = fseek(fout,p->start,SEEK_SET);
char buffer[BUFF_SIZE]; //buffer
long read_size = BUFF_SIZE; //the size for read
long left = p->segment_size; //current left bytes
long read_len = 0; //the size has read
long total_len = 0; //the readed total size
printf("Thread %d begin\t",p->id);
printf("start %ld\t",p->start);
printf("segment_size %ld\t",p->segment_size);
printf("src %s\t",p->src);
printf("dest %s\n",p->dest);
//begin copy
while(left > 0)
{
if(left < read_size)
{
read_size = left;
}
//read file
read_len = fread(buffer,sizeof(char),read_size,fin);
total_len += read_len;
//write file
if(read_len > 0)
{
fwrite(buffer,sizeof(char),read_len,fout);
}
//the left size
left -= read_len;
}
fclose(fin);
fclose(fout);
pthread_mutex_unlock(&mut);
pthread_exit(NULL);
}
//create multi thread
int multi_copy(const char *dest,const char *src)
{
//file is exists
int file_exists = access(src,04);//read access
if(file_exists != 0)
{
fprintf(stderr,"file is not exists!\n");
return 1;
}
int dest_file_exists = access(dest,04);
if(dest_file_exists != 0)
{
fprintf(stderr,"File %s not exists,create it\n",dest);
FILE *cfp = fopen(dest,"w");
fclose(cfp);
}
//file size
long filesize = file_size(src);
//pthread number
int real_pthread_number = PTHREAD_NUMBER;
if(filesize < BUFF_SIZE)
{
real_pthread_number = 1;
}
Page *p = (Page *)malloc(sizeof(Page) * real_pthread_number);
long offset = 0; //offset from file begin
long segment = filesize / real_pthread_number; //the bytes of every thread
long segment_remain = filesize % real_pthread_number; //the left bytes for the last thread
//ctor the task_info
int i;
for(i = 0;i < real_pthread_number;i++)
{
if((i + 1) == real_pthread_number)
{
p[i].segment_size = segment + segment_remain;
}
else
{
p[i].segment_size = segment;
}
//task file pointer offset
p[i].start = offset;
offset += p[i].segment_size;
//file path
strncpy(p[i].src,src,strlen(src));
strncpy(p[i].dest,dest,strlen(dest));
//virtual thread id
p[i].id = i;
}
//create thread
pthread_mutex_init(&mut,NULL);//init thread lock
pthread_t work[real_pthread_number];
for(i = 0;i < real_pthread_number;i++)
{
pthread_create(&work[i],NULL,(void *)&pthread_copy,(void *)&p[i]);
}
//wait subthread exit
for(i = 0;i < real_pthread_number;i++)
{
pthread_join(work[i],NULL);
}
//free
if(p != NULL)
{
free(p);
p = NULL;
}
return 0;
}