Linux线程池添加任务实现拷贝目录下的所有文件

  1. 思路:
			1.创建初始化线程池
			2.编写函数,其作用是递归查找目录下所有文件
			3.将创建目录或者创建文件的任务添加到任务池中
			4.完成目录的拷贝

2.线程池代码

#include "thread_pool.h"
#define TASK_MAX 1024
#define THREADS_MAX 20

void handle(void*arg)
{
    thread_pool* pool = (thread_pool*)arg;
    pthread_mutex_unlock(&pool->mutex);
}
//线程函数
void*thread_running(void* arg)
{
    thread_pool* pool = (thread_pool*)arg;
    struct task_node*p = NULL;//指向 要执行的任务节点
    while(1)
    {
        //上锁之前注册一个清理函数,避免被取消死锁
        pthread_cleanup_push(handle,pool);
        //1.上锁访问任务队列
        pthread_mutex_lock(&pool->mutex);


        //2. 访问任务队列
        // 无任务且线程池未关闭  wait
        while(pool->h->num == 0 && !pool->shutdown)//被唤醒之后检测条件是否依然满足
        {
            pthread_cond_wait(&pool->cond, &pool->mutex);
            //唤醒:
            //1. 有任务
            //2. 线程池要关闭的时候
        }

        // 无任务且线程池关闭  线程死亡
        if(pool->h->num == 0 && pool->shutdown)
        {
            //先解锁在退出
            pthread_mutex_unlock(&pool->mutex);
            pthread_exit(NULL);
        }

        // 有任务开始在任务队列上拿去任务节点
        p = pool->h->first;
        pool->h->first = p->next;// pool->h->first = pool->h->first->next;
        pool->h->num--;


        //拿去任务之后解锁
        pthread_mutex_unlock(&pool->mutex);

        //出栈刚刚注册用不到的清理函数
        pthread_cleanup_pop(0);

        //3. 执行任务
        //执行任务之前设置不可被取消
        pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
        //执行任务
        p->do_task(p->arg);// 使用函数指针调用任务函数
        //执行任务之后设置可被取消
        pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
       
        free(p);
        p = NULL;
    }
}
/*
    init_pool:初始化一个线程池
    @pool: 指向要初始的线程池
    @thread_num:线程池中的活动线程数

    返回值:
        成功 返回true
        失败 返回false
*/
bool init_pool(thread_pool*pool,int thread_num)
{
    pthread_mutex_init(&pool->mutex, NULL);//初始互斥锁
    pthread_cond_init(&pool->cond, NULL);//初始条件变量

    pool->shutdown = false;//非 关闭状态

    pool->task_max = TASK_MAX;

    pool->h = malloc(sizeof(struct Head));//任务队列头节点指针
    if(pool->h == NULL)
        return false;
    pool->h->first = pool->h->last = NULL;
    pool->h->num = 0;//任务队列的节点数 0 

    pool->threads_max = THREADS_MAX;//线程最大数
    if(thread_num > THREADS_MAX)
        pool->threads_num = THREADS_MAX;//活动线程数
    else
        pool->threads_num = thread_num;

    pool->tid = malloc(THREADS_MAX*sizeof(pthread_t));//指针,指向线程ID数组空间
    if(pool->tid == NULL)
    {
        printf("失败:%d\n",__LINE__);
        free(pool->h);
        return false;
    }
       
    
    for(int i = 0; i < pool->threads_num; i++)
    {
        int re = pthread_create(&pool->tid[i], NULL, thread_running, pool);
        if(re == -1)
        {
            perror("pthread_create :");
            printf("失败:%d\n",__LINE__);
            return false;
        }
    }

    return true;
}

/*
    add_task:往线程池中添加任务
    @pool :执行要操作的线程池
    @do_task:函数指针
                执行要执行的任务函数
    @arg: 任务函数 的参数


    返回值:
        成功 真
        失败  假
*/
bool add_task(thread_pool*pool,void*(*do_task)(void*),void*arg)
{
    if(pool == NULL)
    {
        printf("失败:%d\n",__LINE__);
        return false;
    }
        
    //创建新节点
    struct task_node*pnew = malloc(sizeof(*pnew));
    if(pnew == NULL)
    {
        printf("失败:%d\n",__LINE__);

        return false;
    }
        
    pnew->do_task = do_task;
    pnew->arg = arg;
    pnew->next = NULL;

    //增加到任务队列上
    pthread_mutex_lock(&pool->mutex);
    //任务队列满队
    if(pool->h->num == pool->task_max)
    {
        printf("失败:%d\n",__LINE__);
        free(pnew);
        printf("失败:%d\n",__LINE__);
        pthread_mutex_unlock(&pool->mutex);
        printf("失败:%d\n",__LINE__);
        return false;
    }

    if(pool->h->num == 0)//空队列
    {
        pool->h->first = pool->h->last = pnew;
    }
    else
    {
        pool->h->last->next = pnew;
        pool->h->last = pnew;
    }
    pool->h->num++;

    pthread_mutex_unlock(&pool->mutex);
    //唤醒任意一个睡眠线程
    pthread_cond_signal(&pool->cond);
    return true;

}

/*

*/
bool destroy_pool(thread_pool*pool)
{
    pool->shutdown = true;//开关  是否关闭
    //唤醒所有的睡眠线程
    pthread_cond_broadcast(&pool->cond);
    //等待所有活动线程死亡
    for(int i = 0; i < pool->threads_num; i++)
    {
        pthread_join(pool->tid[i], NULL);
    }

    free(pool->h);
    free(pool->tid);//指针,指向线程ID数组空间

    pthread_mutex_destroy(&pool->mutex);//互斥锁
    pthread_cond_destroy(&pool->cond);//条件变量

    //free(pool);
    return true;
}

3.线程池头文件代码

#ifndef __THREAD_POOL__
#define __THREAD_POOL__
#include <pthread.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
struct task_node
{
    void*(*do_task)(void*);
    void*arg;
    struct task_node*next;
};
struct Head//队列头节点
{
    struct task_node* first;
    struct task_node* last;
    int num;
};
//声明线程池类型
typedef struct thread_pool
{
    pthread_mutex_t mutex;//互斥锁
    pthread_cond_t cond;//条件变量

    bool shutdown;//线程 是否关闭

    int task_max;//最大任务数

    struct Head*h;//任务队列头节点指针

    int threads_max;//线程最大数
    int threads_num;//活动线程数

    pthread_t *tid;//指针,指向线程ID数组空间

    //。。。

}thread_pool;

extern bool init_pool(thread_pool*pool,int thread_num);

extern bool add_task(thread_pool*pool,void*(*do_task)(void*),void*arg);

extern bool destroy_pool(thread_pool*pool);

#endif

4.main.c代码

#include <stdio.h>
#include "thread_pool.h"
#include <sys/types.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <pthread.h>
#include <stdlib.h>
#include <strings.h>
pthread_mutex_t g_mutex_cp;
int g_value_cp = 0;

typedef struct fname
{
    char cp_FileArr[2048];//被拷贝的地址
    char pa_FileArr[2048];//目标地址

    DIR *dir;
    struct dirent *p ;

    thread_pool *pool; //线程池相关

}filename_t, *filename_p;

filename_t fileNames[20]; //防止多线程对同一份文件践踏
int Fnames = -1;  //用作数组下标

//创建文件夹
void *cpfile(void * fileName) 
{
    filename_p fileName_pth = (filename_p)fileName;

        mkdir(fileName_pth->pa_FileArr, 0777);
     
        
}



//创建文件
void *cpfile1(void * fileName)
{

     filename_p fileName_pth = (filename_p)fileName;
    int fd1 = open(fileName_pth->cp_FileArr, O_RDWR);

        int fd2 = open(fileName_pth->pa_FileArr, O_RDWR | O_CREAT | O_TRUNC, 777);   

        int ret;
        while(1)
        {
            char buf[16] = {0};
            ret = read(fd1, buf, 16);
            if(ret == 0) break;
            write(fd2, buf, ret);
        }

        close(fd1);
        close(fd2);

    
    }



void Tast(filename_t fileName_F)
{
    filename_t fileName = fileName_F;
    
    fileName.p = readdir(fileName.dir);
    
    
    if(fileName.p == NULL)
    {
        closedir(fileName.dir); //递归出口
        return;
    }//过滤 . 和 ..
    else if(strcmp(fileName.p->d_name, "..") == 0 || strcmp(fileName.p->d_name, ".") == 0)
    {
        Tast(fileName);
    }
    else
    {
       
        char buf_cp[2048] = {0};//缓冲区
        sprintf(buf_cp, "%s/%s", fileName.cp_FileArr, fileName.p->d_name); //当前被拷贝的路径

        char buf_pa[2048] = {0};//缓冲区
        sprintf(buf_pa, "%s/%s", fileName.pa_FileArr, fileName.p->d_name); //当前要拷贝的路径
        
        if(fileName.p->d_type == DT_DIR)//如果是目录
        {
             Fnames++;
            strcpy(fileNames[Fnames].cp_FileArr, buf_cp);   //更新目录
            strcpy(fileNames[Fnames].pa_FileArr, buf_pa);   //更新目录.          
        
            fileNames[Fnames].p = fileName.p;
            fileNames[Fnames].pool = fileName.pool;

            add_task(fileNames[Fnames].pool, cpfile, (void*)&fileNames[Fnames]);

            fileNames[Fnames].dir = opendir(fileNames[Fnames].cp_FileArr);//进入文件夹
            Tast(fileNames[Fnames]);//调用自己

            Tast(fileName);//回溯后继续判断是文件夹还是普通文件
           
        }
        else if(fileName.p->d_type == DT_REG)//如果是普通文件
        {

           Fnames++;

            strcpy(fileNames[Fnames].cp_FileArr, buf_cp);   //更新目录
            strcpy(fileNames[Fnames].pa_FileArr, buf_pa);   //更新目录.
            fileNames[Fnames].p = fileName.p;				//传参
            fileNames[Fnames].pool = fileName.pool;			//传参



            bool ret =  add_task(fileName.pool, cpfile1, (void*)&fileNames[Fnames]);//添加任务

            Tast(fileName);//递归调用
        }
    }
}





int main(int argv, char **argc)
{
    pthread_mutex_init(&g_mutex_cp, NULL);

    filename_t fileName;

    strcpy(fileName.cp_FileArr, argc[1]);
   
    strcpy(fileName.pa_FileArr, argc[2]);

    fileName.pool = malloc(sizeof(*fileName.pool));//创建线程池

    fileName.dir = opendir(fileName.cp_FileArr);

    init_pool(fileName.pool,20);


    Tast(fileName);

    destroy_pool(fileName.pool);
    free(fileName.pool);
}
  • 7
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值