linux下c語言實現多線程文件複製

一、具體思路ubuntu

把一個文件分紅N份,分別用N個線程copy,緩存

每一個線程只讀取指定長度字節大小的內容函數

最後一個線程的源文件所指定的結束位置是文件的實際大小線程

每一個線程讀取指定源文件部分的起始位置和結束位置的內容到緩衝區指針

每一個線程將緩存中的內容寫入目的文件的指定開始位置和結束位置blog

主線程必須等到全部線程copy完成後才能退出資源

2.有關文件操做的函數get

2.1. 文件的打開和關閉it

2.1.1 open()函數 編譯

open()函數的做用是打開文件, 其調用格式爲:

int open(char *filename, int access); 

該函數表示按access的要求打開名爲filename的文件,

返回值爲文件描述字

open()函數打開成功, 返回值就是文件描述字的值(非負值), 不然返回-1。 

2.1.2 close()函數

close()函數的做用是關閉由open()函數打開的文件, 其調用格式爲:

int close(int handle); 

該函數關閉文件描述字handle相連的文件。

2.2.讀寫函數

2.2.1 read()函數

read()函數的調用格式爲:

int read(int handle, void *buf, int count); 

read()函數從handle(文件描述字)相連的文件中, 讀取count個字節放到buf所指的緩衝區中,

返回值爲實際所讀字節數, 返回-1表示出錯。返回0 表示文件結束。

2.2.2 write()函數

write()函數的調用格式爲:

int write(int handle, void *buf, int count); 

write()函數把count個字節從buf指向的緩衝區寫入與handle相連的文件中,

返回值爲實際寫入的字節數

2.3.隨機定位函數

lseek()函數

lseek()函數的調用格式爲:

int lseek(int handle, long offset, int fromwhere); 

該函數對與handle相連的文件位置指針進行定位, 功能和用法與fseek() 函數相同。

3.源文件(copyfn.c)

源文件在ubuntu10.04下編譯經過

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define THREADS_COUNT 3

#define THREADS_BUFF_SIZE 1*1024

struct thread_block

{

int infd; ///源文件句柄

int outfd;//目的文件句柄

size_t start;///文件的寫入起始位置

size_t end; ///文件寫入的終止位置

};

void usage()

{

printf("copy %%src %%dst\n");

}

///獲取文件大小

size_t get_filesize(int fd)

{

struct stat st;

fstat(fd,&st);

return st.st_size;

}

void *thread_copy_fn(void *arg);

int main(int argc,char *argv[])

{

if(argc < 3)

{

usage(); 

return -1;

}

///打開文件

int infd = open(argv[1],O_RDONLY);

int outfd = open(argv[2],O_CREAT|O_WRONLY,0644);

// 0644也就是-文件全部者有讀寫權限,組有讀權限,其餘用戶有讀權限

if(infd == -1|| -1 ==outfd)

{

printf("error while open file \n");

return -1;

}

size_t file_size = get_filesize(infd);

size_t thread_size = THREADS_COUNT;

struct thread_block *blocks = (struct thread_block *)

malloc(sizeof(struct thread_block )* thread_size);

size_t percent = file_size / thread_size;

printf("filesize = %d\t percent_blocks = %d\n",\

file_size,percent);

int i = 0;

//init-thread-block

for(; i < thread_size;++i)

{

blocks[i].infd = infd;

blocks[i].outfd = outfd;

blocks[i].start = i * percent;

blocks[i].end = blocks[i].start + percent;

}

//the last thread

blocks[i].end = file_size;

pthread_t ptid[thread_size]; 

///建立線程

for(i = 0 ; i < thread_size; ++i)

{

pthread_create(&ptid[i],NULL,thread_copy_fn,&(blocks[i]));

}

///線程Join

for(i = 0 ; i < thread_size; ++i)

{

pthread_join(ptid[i],NULL);

}

///釋放資源

free(blocks);

close(infd);

close(outfd);

printf("Copy Successfully \n");

return 0;

}

void *thread_copy_fn(void *arg)

{

struct thread_block *block = (struct thread_block *)arg;

char buf[THREADS_BUFF_SIZE]; 

int ret;

size_t count = block->start;

printf("In Thread\t%ld\nstart = %ld\t end = %ld\n",\

pthread_self(),block->start,block->end);

///lseek到一樣的位置

ret = lseek(block->infd,block->start,SEEK_SET);

ret = lseek(block->outfd,block->start,SEEK_SET);

int bytes_read;

int bytes_write;

while(count < block->end)

{

bytes_read = read(block->infd,buf,sizeof(buf));

if(bytes_read >0)

{

printf("thread = %ld\t read = %ld\t count %d\n",\

pthread_self(),bytes_read,count);

count += bytes_read;

//read()返回-1,同時errno爲EINTR,表示讀的過程當中遇到了中斷

if((bytes_read == -1)&&(errno !=EINTR))

break;

char *ptr_write = buf;

while((bytes_write = write(block->outfd,ptr_write,bytes_read))!=0)

{

//write()會返回-1,同時errno爲EINTR,表示在寫的過程當中遇到了中斷

if((bytes_write == -1)&&(errno!=EINTR))

break;

if(bytes_write == bytes_read)

break;

else if(bytes_write > 0)

{

ptr_write += bytes_write;

bytes_read -= bytes_write;

}

printf("thread = %ld\t write = %ld\t read %d\n",\

pthread_self(),bytes_write,bytes_read);

}//end-write;

///error while write

if(bytes_write == -1)

break;

}

}

printf("#####Thread exit %ld#####\n",pthread_self());

pthread_exit(NULL);

}

本文歡迎轉載,轉載請註明做者與出處

做者:流星

出處:http://blog.sina.com.cn/staratsky

相關文章
相關標籤/搜索