简单多线程拷贝单文件示例
整理以前的代码,发现这个还有个尾巴没有做。
于是花了点时间捡起来。
代码如下
View Code
/*
* =====================================================================================
*
* Filename: copy.c
*
* Description: 多线程拷贝文件
*
* Version: 1.0
* Created: 03/17/2012 04:53:09 AM
* Revision: none
* Compiler: gcc
*
* Author: YOUR NAME (),
* Company:
*
* =====================================================================================
*/
#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 5
#define THREADS_BUFF_SIZE 1*108
/**
@note 传递到线程的参数
*/
struct thread_block
{
int infd; ///<*文件句柄
int outfd;
size_t start;///<*文件的写入起始位置
size_t end; ///<* 文件写入的终止位置[first ,last)开区间
};
void usage()
{
printf("copy %%src %%dst\n");
}
///获取文件大小
size_t get_filesize(int fd)
{
struct stat st;
//memset(&st,0,sizeof(struct stat));
fstat(fd,&st);
return st.st_size;
}
/**
@brief 复制Copy线程
*/
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);
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;
}
/**
* @brief 线程实现函数
* */
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;
//error while read
if((bytes_read == -1)&&(errno !=EINTR))
break;
char *ptr_write = buf;
//悲剧的少了个括号,于是bytes_write == 1
while((bytes_write = write(block->outfd,ptr_write,bytes_read))!=0)
{
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;
}//end-if
}//end-read
printf("#####Thread exit %ld#####\n",pthread_self());
pthread_exit(NULL);
}
输入 ./a.out copy.c copy.c.bk > log
结果如下
相关解释
1.两个宏定义,可以修改
2.针对参数还可以更加多样化。
3.由于是从不同的地方读取和写入到不同的位置,所以对线程没有做任何同步操作。
4.不存在共享数据,由于线程中的buf是线程栈中的数据,不存在共享的问题,所以也不需要做互斥。
5.下一步可以考虑添加监视线程,这样可以达到线程之间的通信功能。
6.线程的调度功能,当一个线程完成自己的任务时,从新获取新的任务执行——需要实现一个任务队列。
参考资料