小白linux入门——每日一记——— 线程池拷贝目录

写了一天的这个项目,对于我一个小白来说,线程池是跟指针有的一拼的东西 不过经过一天的练习也对这个有了一个大概的理解了,我自己的理解就是:子线程从链表拿函数去处理!利用互斥锁和条件变量来保持线程池和链的不冲突。

(程序应该是没有bug的了! 吧????)

main.c

#include "myhead.h"
#include "thread.h"

#define FILE0 "/mnt/hgfs/zjp/album"
#define FILE1 "/mnt/hgfs/zjp/12223"
/*void *copyfile(void *arg)                        //以系统IO为参照  
{

    int r_len;
    char buf[4096];
    struct file *file = (struct file *)arg;
    struct stat src_file;
    stat(file->src,&src_file);
    int fd = open(file->src,O_RDWR);
    if(fd == -1)
    {
        perror("src文件无法打开!\n");
        close(fd);
        return ;
    }

    int fd1 = open(file->des,O_RDWR|O_CREAT|O_TRUNC,0777);
    if(fd1 == -1)
    {
        perror("文件des打开失败!\n");
        close(fd1);
        return ;
    }
    while(r_len = read(fd,buf,4096) != 0)
    {
        write(fd1,buf,strlen(buf));

    } 
    close(fd);
    close(fd1);


}*/
void *copyfile(void *arg)                      //以标准IO为参照,读取二进制文件
{
    char buf[1024];
    struct file *tmp = (void *)arg;

    FILE *fp = fopen(tmp->src,"ab+");
    if(fp == NULL)
    {
        perror("打开文件失败!\n");
        return ;
    }
    FILE *fp1 = fopen(tmp->des,"wb+");
    if(fp1 == NULL)
    {
        perror("打开文件失败!\n");
        return ;
    }
    while(feof(fp) == 0)
    {
        int r_ment = fread(buf,sizeof(buf),1,fp);
        if(r_ment == 1)
        {
            fwrite(buf,sizeof(buf),1,fp1);
        }
        else
        {
            fwrite(buf,strlen(buf),1,fp1);
        }
        memset(buf,0,sizeof(buf));
    }
    fclose(fp);
    fclose(fp1);

}

int copydir(struct threadpool *pool,struct file *file)    //文件夹的检索,判断是否为文件 文件进链,文件夹递归
{
    struct stat file_stat;
    stat(file->src,&file_stat);

    mkdir(file->des,file_stat.st_mode);
    DIR *s_dir = opendir(file->src);
    struct dirent *dp;

    while((dp = readdir(s_dir)) != NULL)
    {
        if(dp->d_name[0] == '.' )
        {
            continue;
        }

        struct file *tmp = malloc(sizeof(struct file));
        memset(tmp ,0,sizeof(struct file));

        sprintf(tmp->src,"%s/%s",file->src,dp->d_name);
        sprintf(tmp->des,"%s/%s",file->des,dp->d_name);

        struct stat tump;
        stat(tmp->src,&tump);
        if(S_ISREG(tump.st_mode))                       //如果为普通文件,则拷贝
        {
            printf("src= %s\n",tmp->src);
            printf("new->dst = %s\n", tmp->des);

            add_pool(copyfile,tmp,pool);        

            // printf("加入链表成功!\n"); 
        }
        else if(S_ISDIR(tump.st_mode))//如果为目录,则递归
        {   
            copydir(pool,tmp);
        }
    }
    return 0;
}
int main(int argc, char **argv)
{
    /*if(argc != 3)
    {
        perror("输入的格式有误!\n,请输入格式为./xxx(源文件) xxx(源目录) xxx(拷贝目录)");
        return -1;
    }
*/
    time_t star,end;
    star = time(NULL);
    struct threadpool *mypool = malloc(sizeof(struct threadpool));  //定义一个线程池空间
    pool_init(10,mypool);                                           //线程池初始化

    struct file catfile;
    strcpy(catfile.src,/*argv[1]*/FILE0);
    strcpy(catfile.des,/*argv[2]*/FILE1);

    struct stat src_dir;
    stat(catfile.src,&src_dir);  //对文件进行判断!判断文件or文件夹

    if(S_ISREG(src_dir.st_mode))
    {

        copyfile(&catfile);             //对文件进行复制!
    }
    else if(S_ISDIR(src_dir.st_mode))
    {
        copydir(mypool,&catfile);               //对文件夹进行复制!
    }
    else
    {
        perror("无法识别的文件!\n");
        return -1;
    }

    destory_pool(mypool);
    end = time(NULL);
    printf("复制用时:%f\n",difftime(end,star));

    return 0;
}

线程池函数

#ifndef _THREAD_H_
#define _THREAD_H_
#include "myhead.h"

#define MAX 4096

struct node
{
    void *arg;
    void *(*node)(void *arg);//需要处理的函数!

    struct node *next;
};

struct file
{
    char src[MAX];
    char des[MAX];
};

struct threadpool
{

    int tasknum;                //链表的结点的个数
    int threadnum;              //线程的个数

    bool poolswitch;            //条件变量
    struct node *head;          //线程池的存在标志

    pthread_t *threadid;        //线程的ID
    pthread_mutex_t poolmutex;  //互斥锁
    pthread_cond_t poolcond;   

};

void clean(void *arg);
void *gettask (void *arg);
void *copyfile (void *arg);
int destory_pool(struct threadpool *pool);
bool pool_init(int n,struct threadpool *mypool);
int remove_thread(struct threadpool *pool,int remove);
int copydir(struct threadpool *pool,struct file *file);
bool add_pool( void *(*task)(void *arg) , void *arg,struct threadpool *pool);
// bool add_pool(void *(*task)(void *),void *arg,struct threadpool *pool);

// void *fun(void *arg)
// {
//  printf("输出测试!\n");
// }
// int main(void)
// {
//  int i = 5;
//  struct threadpool *pool = malloc(sizeof(struct threadpool));

//  pool_init(5,pool);
//  while(i--)
//  add_pool(fun,NULL,pool);

//  destory_pool(pool);
//  return 0;
// }
void clean(void *arg)
{
    pthread_mutex_unlock((pthread_mutex_t *)arg);
}
void *gettask (void *arg)
{
    struct threadpool *pool = (struct threadpool *)arg;
    struct node *p;
    if(pool == NULL)
    {
        perror("传递的线程池失败!\n");
        return ;
    }

    while(1)
    {   

        pthread_cleanup_push(clean,(void *)&(pool->poolmutex));         //防止死锁

        pthread_mutex_lock(&(pool->poolmutex));


        while((pool->tasknum == 0) && (!pool->poolswitch ))
        {
            /*printf("判断是否卡住!\n");*/
            pthread_cond_wait(&(pool->poolcond),&(pool->poolmutex));
        }
        if(pool->tasknum == 0 && pool->poolswitch == true)
        {
            pthread_mutex_unlock(&pool->poolmutex);
            pthread_exit(NULL);
        }       

        p = pool->head->next;
        pool->head->next = p->next;
        pool->tasknum--;



        pthread_mutex_unlock(&pool->poolmutex);
        pthread_cleanup_pop(0);

        pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
        (p->node)(p->arg); 
        pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);

        free(p->arg);
        free(p);

    }
    pthread_exit(NULL); 
}

bool pool_init(int n,struct threadpool *mypool)
{
    int i;

    int pmi = pthread_mutex_init(&mypool->poolmutex,NULL);      //互斥锁初始化!

    int pci = pthread_cond_init(&mypool->poolcond,NULL);        //条件变量的初始化!

    mypool->threadnum = n;                                      //线程数目
    mypool->tasknum = 0;                                        //结点数目

    mypool->head = malloc(sizeof(struct node));     
    memset(mypool->head,0,sizeof(struct node));         //头结点初始化
    mypool->head->next = NULL;


    mypool->threadid = malloc(sizeof(pthread_t)*1000);          //线程ID的空间的分配

    mypool->poolswitch = false;                                 //线程池的标志


    for(i = 0; i < (mypool->threadnum); i++)                                      //生成对应的线程并调用线程函数进行工作
    {
        if(pthread_create(&((mypool->threadid)[i]),NULL,gettask,(void*)mypool) == 0)
        {
            printf("测试:线程%d已建立!\n",i);
        }
    }

}
bool add_pool(void *(*task)(void *),void *arg,struct threadpool *pool)
{
    pthread_mutex_lock(&pool->poolmutex);

    struct node *network = malloc(sizeof(struct node));
    if(network == NULL)
    {
        perror("生成空间失败!\n");
        return false;
    }

    network->node = task;
    network->arg  = arg;
    network->next = NULL;

    struct node *tmp = pool->head;
    while((tmp->next) != NULL)
    {

        tmp = tmp->next;

    }

    tmp->next = network;

    pool->tasknum++;

    pthread_mutex_unlock(&(pool->poolmutex));
    pthread_cond_signal(&pool->poolcond);

    return true;
}
int remove_thread(struct threadpool *pool,int remove)
{
    int i;
    if(remove == 0)
    {
        return 0;
    }
    else if(remove > pool->threadnum)
    {
        return -1;
    }
    else
    {
        for(i = pool->threadnum;i = (pool->threadnum -remove);i--)
        {
            pthread_cancel(pool->threadid[i]);
        }
    }
}

int destory_pool(struct threadpool *pool)
{
    int i;
    pool->poolswitch = true;
    pthread_cond_broadcast(&pool->poolcond);

    for(i = 0; i < pool->threadnum;i++)
    {
        pthread_join(pool->threadid[i],NULL);
        printf("%d号线程退出 退出的pid:%d\n",i,(int)pool->threadid[i]);
    }

    free(pool->head);
    free(pool->threadid);
    free(pool);
}
#endif

自己的头文件

#ifndef _MYHEAD_H_
#define _MYHEAD_H_
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include

#endif

你可能感兴趣的:(小白linux入门——每日一记——— 线程池拷贝目录)