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

 1、具體思路
把一個文件分成N份,分別用N個線程copy,
每個線程只讀取指定長度字節大小的內容
最後一個線程的源文件所指定的結束位置是文件的實際大小
每個線程讀取指定源文件部分的起始位置和結束位置的內容到緩衝區
每個線程將緩存中的內容寫入目的文件的指定開始位置和結束位置
主線程必須等到所有線程copy完成後才能退出
 
2.有關文件操作的函數
2.1. 文件的打開和關閉
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 <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
 
#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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章