linuxの下でc言語はマルチスレッドファイルのコピーを実現します
6172 ワード
1、具体的な考え方
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)
ソースファイルはubuntu 10にあります.04次コンパイルパス
本文は転載を歓迎して、転載して作者と出典を明記してください
作者:流星
出典:http://blog.sina.com.cn/staratsky
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)
ソースファイルはubuntu 10にあります.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
");
}
///
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
");
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
",\
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
");
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
start = %ld\t end = %ld
",\
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
",\
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
",\
pthread_self(),bytes_write,bytes_read);
}//end-write;
///error while write
if(bytes_write == -1)
break;
}
}
printf("#####Thread exit %ld#####
",pthread_self());
pthread_exit(NULL);
}
本文は転載を歓迎して、転載して作者と出典を明記してください
作者:流星
出典:http://blog.sina.com.cn/staratsky