线程池与cp命令的实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/s564200489/article/details/50538781

用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

猜你喜欢

转载自blog.csdn.net/s564200489/article/details/50538781
今日推荐