基于linux下的线程池复制多级目录及文件
来源:互联网 发布:ubuntu怎么安装jdk1.8 编辑:程序博客网 时间:2024/05/21 17:08
1. 设计目标
拷贝指定文件夹下的所有子文件夹和文件,利用多线程加快拷贝速度。
2.设计方案
./xxx /源文件夹 /目标文件夹
递归遍历文件夹下所有文件,为文件夹便创建,为文件便复制
总是先创建文件夹,再复制文件,将复制文件投入线程池任务列队
3.系统框架
4.源码分析
4.1 线程池接口函数
#define MAX_WAITING_TASKS 20000#define MAX_ACTIVE_THREADS 20struct task{ void *(*do_task)(void *arg); void *arg; struct task *next;};typedef struct thread_pool{ //互斥量和条件变量 pthread_mutex_t lock; pthread_cond_t cond; //停止标志位 bool shutdown; //任务链表 struct task *task_list; //线程号数组 pthread_t *tids; unsigned max_waiting_tasks; unsigned waiting_tasks; unsigned active_threads;}thread_pool;//线程池初始化 threads_number->初始线程数bool init_pool(thread_pool *pool, unsigned int threads_number);//添加任务进线程池 do_task->功能函数(实际使用只需将此函数改为自己需要的功能函数即可)bool add_task(thread_pool *pool, void *(*do_task)(void *arg), void *arg);//添加线程int add_thread(thread_pool *pool, unsigned int additional_threads_number);//移除线程int remove_thread(thread_pool *pool, unsigned int removing_threads_number);//销毁线程池bool destroy_pool(thread_pool *pool);void *routine(void *arg);
4.2文件操作函数框架
#define SIZE 512char filecwd[SIZE];char dircwd[SIZE];//定义文件的结构体struct filepath{ char filesp[SIZE]; char filedp[SIZE];};void rootdir(char sp[SIZE],char dp[SIZE]);void printdir(char *dir,char sp[SIZE],char dp[SIZE],thread_pool *pool);void replace_string(char * source_str,char * targ_str,char *val);void mk_dir(char dpath[]);void* copy_file(void *arg);#endif
4.3遍历目录函数
void printdir(char *dir,char sp[SIZE],char dp[SIZE],thread_pool *pool){ //打开目录指针 DIR *Dp; //文件目录结构体 struct dirent *enty; //详细文件信息结构体 struct stat statbuf; //打开指定的目录,获得目录指针 if(NULL == (Dp = opendir(dir))) { fprintf(stderr,"can not open dir:%s\n",dir); return; } //切换到这个目录 chdir(dir); //遍历这个目录下的所有文件 while(NULL != (enty = readdir(Dp) )) { //通过文件名,得到详细文件信息 lstat(enty->d_name,&statbuf); //判断是不是目录 if(S_ISDIR(statbuf.st_mode)) { if(0 == strcmp(".",enty->d_name) || 0 == strcmp("..",enty->d_name)) //当前目录和上一目录过滤掉 { continue; } getcwd(dircwd,SIZE); strcat(dircwd,"/"); strcat(dircwd,enty->d_name); //工作路径+目录名 replace_string(dircwd,sp,rindex(sp,'/')); char dirdp[SIZE]; sprintf(dirdp,"%s%s",dp,dircwd); //目录最终绝对路径 mk_dir(dirdp); //创建目录 //递归调用 printdir(enty->d_name,sp,dp,pool); } else { struct filepath fpath; //定义文件路径结构体 char temp_path[SIZE]; getcwd(filecwd,SIZE); sprintf(fpath.filesp,"%s/%s",filecwd,enty->d_name); //源文件绝对路径 strcpy(temp_path,fpath.filesp); //暂存源文件绝对路径 replace_string(temp_path,sp,rindex(sp,'/')); sprintf(fpath.filedp,"%s%s",dp,temp_path); //目标文件绝对路径 add_task(pool, copy_file, (void *)(&fpath)); //添加复制文件任务 usleep(9000); //线程休息时间 } } //切换到上一及目录 chdir(".."); //关闭文件指针 closedir(Dp); } /*据说线程池的线程也需要一定时间休息, 因而我在实际操作中在添加任务add_task()后加了休眠函数usleep(), 否则会导致遗漏任务,休眠的时间根据自己执行的功能函数时间而具体决定*/
/*将字符串中指定子字符串用指定字符串代替,targ_str 是被替换的,val是替换的字符串*/ void replace_string(char * source_str,char * targ_str,char *val){ char temp_sstr[SIZE],result[SIZE]; char *p=NULL,*q=NULL; int len=0; memset(result,0,sizeof(result)); memset(temp_sstr,0,sizeof(temp_sstr)); strcpy(temp_sstr,source_str); p=temp_sstr; q=temp_sstr; len=strlen(targ_str); while(q!=NULL) { if((q=strstr(p,targ_str))!=NULL) { strncat(result,p,q-p); strcat(result,val); strcat(result,"\0"); q+=len; p=q; } else strcat(result,p); } strcpy(source_str,result); }
4.4创建目录及复制文件函数
//创建目录函数void mk_dir(char dpath[]){ mkdir(dpath,S_IRWXU|S_IRGRP|S_IROTH);}//复制文件函数void* copy_file(void *arg){ struct filepath *p = (struct filepath *)arg; //转换 FILE *fb_from,*fb_to; int rd_cnt; char rd_buf[1024]; char path1[SIZE]; char dp1[SIZE]; fb_from = fopen(p->filesp,"r"); if(fb_from == NULL){ printf("read open file failure:%s \n",p->filesp); return NULL;} fb_to = fopen(p->filedp,"w+"); if(fb_to == NULL){ printf("write open file failure: %s \n",p->filedp); return NULL;} while((rd_cnt = fread(rd_buf,sizeof(char),1024,fb_from)) > 0){ fwrite(rd_buf,sizeof(char),rd_cnt,fb_to); fflush(fb_to);} i++; printf("%d copy success : %s\n",i,p->filedp); fclose(fb_from); fclose(fb_to); return NULL;}
void rootdir(char sp[SIZE],char dp[SIZE]){ mkdir(dp,S_IRWXU|S_IRGRP|S_IROTH); //创建目标根目录 char dp1[SIZE]; strcpy(dp1,dp); strcat(dp1,rindex(sp,'/')); mkdir(dp1,S_IRWXU|S_IRGRP|S_IROTH); //创建源根目录}
4.5main函数
#include "thread_pool.h"#include "file.h"int main(int argc,char *argv[]){ if(argc < 3) { printf("path error\n"); return -1; } thread_pool *pool = malloc(sizeof(thread_pool)); //线程池初始化 init_pool(pool, 15); rootdir(argv[1],argv[2]); printdir(argv[1],argv[1],argv[2],pool); destroy_pool(pool); return 0;}
5.最终效果
6.心得笔录
这个小程序主要是靠文件夹递归查找文件为核心实现的,局限在于只能识别目录与一般文件,对管道等文件类型无法识别;
对线程池的理解还不够深,对互锁和条件变量使用不够清楚;
出现过复制丢失文件的情况,原因应该为添加任务后的休息时间,太短容易造成丢失,原因还需研究。
先这样了…加油
2017.8.18 bade
阅读全文
1 0
- 基于linux下的线程池复制多级目录及文件
- 多级文件的复制:复制指定目录下的内容到另一指定目录下
- 删除多级目录下的一类文件
- 创建多级文件夹/目录下的文件
- 用线程池复制目录里目录的文件
- Linux复制指定目录及子目录下特定类型的文件
- Linux下cp(文件及目录复制)命令的总结
- php复制目录下的所有文件及文件夹
- php复制目录下的所有文件及文件夹
- C# 递归复制文件夹及文件夹目录下的文件
- linux下的文件及目录管理
- IO流--多级文件夹下的所有目录复制到指定目录下
- linux下快速删除目录下大量小文件及快速复制大量小文件方法
- 两个linux之间复制文件及目录
- 目录间复制文件的线程实现
- Linux下基于C语言流的文件复制
- python 读取多级目录下所有的文件
- 黑马程序员_多级目录的复制
- [编程题] 操作序列
- node模块之cron
- 《统计学习方法》 朴素贝叶斯 极大使然估计 Python实现
- 简述ElasticSearch里面复杂关系数据的存储方式
- 三分模板
- 基于linux下的线程池复制多级目录及文件
- maven理解
- 免费馅饼题解
- TabLayout与频道拖拽联合+listview多条目+listview点击跳转
- ZOJ 1107 FatMouse and Cheese(记忆化搜索)
- C++读写二进制格式文件
- construct 2 插件初识(2)
- 签到,补签,求最长连续签到多少天
- Python:numpy中array的用处