写了一天的这个项目,对于我一个小白来说,线程池是跟指针有的一拼的东西 不过经过一天的练习也对这个有了一个大概的理解了,我自己的理解就是:子线程从链表拿函数去处理!利用互斥锁和条件变量来保持线程池和链的不冲突。
(程序应该是没有bug的了! 吧????)
#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