线程池与cp命令的实现

来源:互联网 发布:php防止sql注入代码 编辑:程序博客网 时间:2024/04/26 20:39

用Linux C完成shall命令cp的实现
在复制大量文件时,当遇到大量的或较大的文件时,使用单进程单线程进行文件复制效率比较低下,而使用线程池能很好的提高效率。
思路:

1、初始化线程池2、如果需要复制文件则直接复制,如果需要复制文件夹则往下3、遍历文件夹,复制内容4、复制内容任务加入任务链表

线程池

线程池结构体

struct thread_pool{    pthread_mutex_t mutex;//互斥锁    pthread_cond_t cond;//条件变量    int thread_num;//线程池中线程的数量    pthread_t *t;//每个线程的ID    struct task *head;//任务链表头    int cur_queue_size;//任务节点数};

任务结构体

struct task{    void *(*p)(struct tem *);//函数指针    struct tem *arg;//参数实参    struct task  *next;//下一个任务的地址};

在此任务链表为单向链表

主程序

#include "mycp.h"int all_pthread_done = 0;int main (int argc ,char **argv){    struct stat st;    pool_init(4);//初始化线程池    printf("init pool\n");    sleep(1);    stat(argv[1],&st);    struct tem t;//因为线程函数只能传入一个参数所以定义tem结构体包含源目录与目的目录    t.t_s = argv[1];    t.t_o = argv[2];    if (S_ISDIR(st.st_mode))//判断是否为目录        show_dir(argv[1],argv[2]);    else//为文件的话直接复制        {            copy_file(t);        }    all_pthread_done = 1;//告诉子线程所有任务添加完成    printf("finsh!!\n");    pthread_cond_broadcast(&(pool->cond));//唤醒在等待的线程    int i;    for(i=0;i<pool->thread_num;i++)        pthread_join(pool->t[i],NULL);//等待所有线程退出    printf("end\n");    pool_del();//回收线程等    return 0;}

函数

#include "mycp.h"extern int all_pthread_done ;int already_get_tem = 0;void pool_add_task(void *(*pr)(struct tem *),struct tem arg)  //添加任务{    struct task *newtask=malloc(sizeof(struct task));//创建,初始化任务    newtask->p = pr;    newtask->arg = arg;    newtask->next = NULL;    pthread_mutex_lock(&(pool->mutex));//上锁    printf("add task ing cp %s to %s\n",arg.t_s,arg.t_o );    //把newtask节点增加到任务链表尾。    struct task *temp = NULL;    if(pool->head==NULL)        pool->head = newtask;    else    {        temp = pool->head;        pool->head = newtask;        newtask->next = temp;    }    printf("add task fin cp %s to %s\n",newtask->arg.t_s,newtask->arg.t_o );    pool->cur_queue_size++;//任务增加一个    pthread_mutex_unlock(&(pool->mutex));    pthread_cond_signal(&(pool->cond));//告诉子线程任务添加完毕    printf("add task successful!!\n");}void *f(void *reg) //子线程{    struct task *wh;    while(1)   {    pthread_mutex_lock(&(pool->mutex));    printf("wait for task\n");    while((pool->cur_queue_size==0)&&(all_pthread_done==0))//等待任务        pthread_cond_wait(&(pool->cond),&(pool->mutex));    if ((pool->cur_queue_size==0)&&(all_pthread_done==1))//如果没有任务切主线程添加任务完毕则退出    {        pthread_mutex_unlock(&(pool->mutex));        printf("pthread exit\n");        pthread_exit(0);    }    wh = pool->head;    //  将任务从任务列表中取出    pool->head = wh->next;    pool->cur_queue_size--;    printf("get the task %s to %s\n", wh->arg.t_s,wh->arg.t_o);    pthread_mutex_unlock(&(pool->mutex));//读取完节点后解锁    (*(wh->p))(&(wh->arg));//执行任务    printf("copy finsh\n");    free(wh);//释放任务   }}void pool_init(int num){    pool = (struct thread_pool *)malloc(sizeof(struct thread_pool));//初始化线程池    pthread_mutex_init(&(pool->mutex),NULL);//初始化互斥锁    pthread_cond_init(&(pool->cond),NULL);//初始化条件变量    pool->thread_num=num;    pool->head=NULL;    pool->cur_queue_size=0;    pool->t = malloc(sizeof(pthread_t)*num);//建立数组,元素有num个    int i;    for(i=0;i<pool->thread_num;i++)        pthread_create(&(pool->t[i]),NULL,f,&i);//建立三个线程,线程号为pool->t}char * arr(char *frr,char *crr)//{    int i = strlen(crr);    int j = strlen(frr);    char *a = malloc(sizeof(char)*(i+j+1+1));    sprintf(a,"%s/%s",frr,crr);    printf("arr a = %s\n", a);    return a;}char * arr_file(char *frr,char *crr){    int i = strlen(crr);    int j = strlen(frr);    char *a = malloc(sizeof(char)*(i+j+1+1));    if (frr[strlen(frr)]=='/')        sprintf(a,"%s%s",frr,crr);    else        sprintf(a,"%s/%s",frr,crr);    printf("arr_file a: %s\n", a);    return a;}char *arr_m(char *mdir,char *pdir){    if (mdir[0]=='.')    {        int i = 0,j;        j = strlen(mdir)+1;        printf("star %d j = %d, %c \n", i,j,mdir[0]);        sleep(1);        while(i < j)        {            sleep(1);            mdir[i] = mdir[++i];            printf("%d\n",i );        }    }    char *a = malloc(sizeof(char)*(strlen(mdir)+strlen(pdir)+1));    sprintf(a,"%s%s",pdir,mdir);    printf("arr_m a = %s\n", a);    sleep(3);    return a;}void * copy(struct tem *te){    printf("copying %s ..to.. %s\n", te->t_s,te->t_o);    int fd1 ,fd2,i=1024;    fd1 = open(te->t_s,O_RDONLY);    char buf[1024];    fd2 = open(te->t_o,O_RDWR|O_CREAT , 0777);    while(i == 1024)    {        i = read(fd1,buf,1024);        write(fd2,buf,i);    }    free(te->t_s);    free(te->t_o);}void copy_file(struct tem te){    printf("%s to %s\n",te.t_s,te.t_o );    char *c = malloc(sizeof(char)*(strlen(te.t_o)+1));    strcpy(c,te.t_o);    printf("c = %s\n", c);    int i ;    for (i = strlen(te.t_o);c[i]!='/';i--);    c[i] = '\0';    mkdir(c,0777);    int fd1 ,fd2;    i=1024;    fd1 = open(te.t_s,O_RDONLY);    char buf[1024];    fd2 = open(te.t_o,O_RDWR|O_CREAT , 0777);    while(i == 1024)    {        i = read(fd1,buf,1024);        write(fd2,buf,i);    }    free(C);}void show_dir(char *mdir,char *pdir)//遍历目录 ./123 ./456   ./123/555 ./456/555{    char *temp,*temp2;    struct dirent * da;    struct tem tem;    DIR * dir = NULL;    printf("mkdiring pdir %s ...\n", pdir);    dir = opendir(mdir);    if(mkdir(pdir,0777)==-1)//先创建目的目录 ./456  ./456/555    {        printf("dir is already exists\n");    }    sleep(1);    while(da = readdir(dir))    {        if(da->d_name[0]=='.')            continue;        if((int)da->d_type==4)//判断原目录下的文件是目录还是普通文件 ./123/555        {            temp = arr(mdir,da->d_name);//得到完整的目录路径 ./123/555            temp2 = arr(pdir,da->d_name);//得到完整的目的目录路径./456/555            show_dir(temp,temp2);            free(temp);            free(temp2);        }else        {            tem.t_s = arr_file(mdir,da->d_name);//得到完整的原文件路径            tem.t_o = arr_file(pdir,da->d_name);//得到完整的目的文件路径            pool_add_task(copy,tem);//添加copy任务            //copy(&tem);  //使用线程去做        }    }    closedir(dir);}void pool_del(void){    pthread_mutex_destroy(&(pool->mutex));    pthread_cond_destroy(&(pool->cond));    free(pool->t);    free(pool);}

mycp.h

#ifndef _MYCP_H_#define _MYCP_H_#include <stdio.h>#include <pthread.h>#include <sys/types.h>#include <dirent.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/stat.h>#include <sys/types.h>#include <fcntl.h>struct tem{    char *t_s;    char *t_o;};struct task{    void *(*p)(struct tem *);    struct tem arg;//参数实参    struct task  *next;};struct thread_pool{    pthread_mutex_t mutex;    pthread_cond_t cond;    int thread_num;    pthread_t *t;    struct task *head;    int cur_queue_size;//任务节点数};struct thread_pool *pool;void pool_add_task(void *(*pr)(struct tem *),struct tem arg); //增加任务void *f(void *reg); //子线程void pool_init(int num);void pool_del(void);void * copy(struct tem *te);void show_dir(char *mdir,char *pdir);char *arr_m(char *mdir,char *pdir);char * arr_file(char *frr,char *crr);char * arr(char *frr,char *crr);void copy_file(struct tem te);#endif
0 0
原创粉丝点击