linux多线程写文件内容丢失,求助,多线程写入文件错乱问题!!~~

一、多线程版本

#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;

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值