主頁 > 作業系統 > 基于linux用執行緒池實作檔案管理

基于linux用執行緒池實作檔案管理

2020-09-10 21:45:59 作業系統

專案要求

1.基本

  用執行緒池實作一個大檔案夾的拷貝,大檔案夾嵌套很多小檔案;實作復制到指定檔案夾的全部檔案夾,

2.擴充功能

  顯示進度條;拷貝耗時統計;類似linux的tree,不能直接用system()與exec()等函式;根據檔案型別拷貝;搜索檔案;洗掉檔案等,(暫時加了這么一些功能)

8月17日補:移動、復制到的目錄已包含該檔案則選擇覆寫或者加命名,

 

實作思路

  先完成基本,逐步完成擴展再優化重構代碼,

 

實作程序

基本功能

  基于linux,通過執行緒池實作的,核心就是執行緒池的三大基本功能--執行緒例程、添加執行緒、銷毀執行緒池,由這三個為基礎,對專案進行展開,基本功能,即通過遞回讀取目錄,通過strucr dirent *p這個結構體來實作判斷檔案型別,如果是普通檔案,直接在新目錄用檔案IO的讀寫實作拷貝功能(包括標準IO、系統IO,還有共享記憶體也可以實作),拷貝那里用“添加執行緒”,保證可以多執行緒實作拷貝;如果是目錄檔案,就先創建檔案夾--mkdir(),再sprintf拼接字串以及函式的遞回實作子級目錄的拷貝,

->拷貝代碼

void *myregcp(void *myarg)
{
    struct copypath *mypath=(struct copypath *)myarg;
    
    //系統IO的復制
    int fd1,fd2;
    fd1=open(mypath->oldpath,O_RDONLY);
    fd2=open(mypath->newpath,O_CREAT|O_TRUNC|O_RDWR,0777);
    if(fd1==-1)
    {
        perror("打開1失敗\n");
        return NULL;
    }
    if(fd2==-1)
    {
        perror("打開2失敗\n");
        return NULL;
    }
    char buf[SIZE];
    int nread,nwrite;
    while(1)
    {
        bzero(buf,SIZE);
        nread=read(fd1,buf,SIZE);
        if(nread==0)
            break;
        cs=cs+nread;
        write(fd2,buf,nread);
    }
    close(fd1);
    close(fd2);    
    return NULL;    
}

->遞回讀取全部目錄

int myreaddir(struct copypath *pp,struct threadpool *pool)
{
    DIR *dirp=opendir(pp->oldpath);
    if(dirp==NULL)
    {
        perror("失敗:\n");
        return -1;
    }
    struct dirent *p;    
    while((p=readdir(dirp))!=NULL)
    {    
        if(p->d_type==DT_REG)        //普通檔案
        {
            struct copypath *mypath=malloc(sizeof(struct copypath));
            sprintf(mypath->oldpath,"%s/%s",pp->oldpath,p->d_name);
            sprintf(mypath->newpath,"%s/%s",pp->newpath,p->d_name);
            add_task(myregcp,mypath,pool);    //實作
        }
        if(p->d_type==DT_DIR)        //檔案夾
        {                
            if(strcmp(p->d_name,".")!=0 && strcmp(p->d_name,"..")!=0)
            {    
                struct copypath *mydirpath=malloc(sizeof(struct copypath));
                sprintf(mydirpath->oldpath,"%s/%s",pp->oldpath,p->d_name);
                sprintf(mydirpath->newpath,"%s/%s",pp->newpath,p->d_name);
                mkdir(mydirpath->newpath,0777);
                myreaddir(mydirpath,pool);
            }
        }
    }
    closedir(dirp);
    return 1;
}

  這樣就大概完成基本功能,用多執行緒實作大檔案夾的拷貝,

擴充功能

->進度條

  定義兩個全域變數,一個用于計算總位元組數,另一個計算每次復制的位元組數,再用一個顯示函式實作進度條的顯示,這里要注意緩沖區的問題,所以我用了"fflush(NULL)"這個函式,讓它每列印一個'|'的時候,就重繪一次緩沖區,計算總的位元組數直接遞回全部目錄,用"struct stat info"這個結構體里面的"info.st_size"累加,即可得到總的位元組數;拷貝功能函式里面有個"cs"變數,就是存放拷貝位元組數,顯示進度條就用簡單的判斷,加相除實作,因為是顯示20個|,所以我乘20,

  num=(float)cs;        //正在復制位元組數
  k=(num/s)*20;    

->耗時

  有三種思路,用clock()、time()、sleep(1)等都可以實作計時,直接在拷貝前和拷貝后加賦值,然后相減,即可,起初自己是用clock()這個函式,但是每次都是三秒,,,然后轉到sleep(),讓它自己while()累加實作,

->代碼實作樹

  還是遞回的思想,遞回如果是普通檔案就列印,是目錄檔案夾就字串拼接再遞回列印子檔案夾下的子檔案,

void dirtree(char dirpath[],int level)
{
    int i;
    char *dirname=NULL;
    int dirlen;
    DIR *dp=opendir(dirpath);
    if(dp==NULL)
    {
        perror("失敗:\n");
        return;
    }
    struct dirent *ep;
    while((ep=readdir(dp))!=NULL)
    {
        if(strncmp(ep->d_name, ".", 1) == 0)
            continue;
        for(i=0;i<level;i++)
        {
            printf("|");
            printf("     ");
        }
        printf("|--- ");
        printf("\033[1;32;40m %s \033[0m\n",ep->d_name);
        if(ep->d_type==DT_DIR)
        {
            //當前目錄長度
            dirlen=strlen(dirpath)+1;
            //備份
            dirname=(char *)malloc(dirlen);
            memset(dirname,0,dirlen);
            memcpy(dirname,dirpath,dirlen);
            
            strcat(dirpath,"/");
            strcat(dirpath,ep->d_name);
            dirtree(dirpath,level+1);        //遞回實作樹效果
            //恢復之前的目錄名
            memcpy(dirpath,dirname,dirlen);
            free(dirname);            
            dirname = NULL;
        }
    }    
    closedir(dp);
}

->按型別拷貝檔案

  也比較簡單,另建一個遞回讀目錄的函式,在普通檔案加個if條件判斷就可以,

  if(strstr(p->d_name,ftype)!=NULL)

->搜索檔案

  類似于win的檔案檢索功能,在輸入那個檔案下面實作相似檔案名的檢索,并列印相關路徑,也是遞回讀取目錄,核心的改變代碼也就一句,用"strstr()"尋找相應的子字串,列印,

  if(strstr(p->d_name,filename)!=NULL)

->洗掉檔案夾

  洗掉稍微要注意一下如果檔案夾下面還有其他檔案,就不能直接用"rmdir"洗掉檔案夾,先用remove()洗掉檔案,之后再洗掉子檔案夾,也是用遞回思想實作的,

 

實作效果

  現在還傳不了,后期再傳吧,

全部代碼

 

#include "myhead.h"
#define SIZE 1024*1024
long int s=0;    //總位元組數
long int cs=0;    //計算每次復制的位元組數
int tm=0;        //計時--以秒為單位
int flag;        //結束標志位
/***************************相關結構體的定義******************************/
struct copypath
{
    char oldpath[256];
    char newpath[256];
    char target[50];
};
//創建任務鏈表結構體
struct tasklist
{
    void *(*taskp)(void *);
    void *taskarg;
    struct tasklist *next;
};
//創建任務鏈表表頭
struct tasklist *myhead;
//初始化任務鏈表
struct tasklist* task_init()
{    
    struct tasklist *mytask=malloc(sizeof(struct tasklist));
    mytask->taskp=NULL;
    mytask->taskarg=NULL;
    mytask->next=NULL;
    return mytask;
}
//創建執行緒池
struct threadpool
{
    int threadnum;//統計當前執行緒數量
    pthread_t *threadid;//存放當前執行緒的ID號
    struct tasklist *taskhead;//保存任務鏈表的頭結點
    pthread_mutex_t threadmutex;//互斥鎖
    int tasknum;//統計任務鏈表中的數量
    pthread_cond_t threadcond;//條件變數
    bool threadflag;//用于判斷執行緒池是否開啟
};

//執行緒的多任務函式
void *routine(void *arg)
{
    struct threadpool *pool=(struct threadpool *)arg;
    //負責從任務鏈表的頭結點的下一個位置取出任務然后處理
    struct tasklist *p;
    while(1)
    {
        //上鎖
        pthread_mutex_lock(&(pool->threadmutex));
        //判斷數量是否為0
        while(pool->threadflag==true && pool->tasknum==0)
        {
            //printf("%ld執行緒阻塞--wait\n",pthread_self());
            pthread_cond_wait(&(pool->threadcond),&(pool->threadmutex));
        }
        if(pool->threadflag==false&&pool->tasknum==0)
        {
            pthread_mutex_unlock(&(pool->threadmutex));
            pthread_exit(NULL);
        }
        //取出節點處理
        p=pool->taskhead->next;
        pool->taskhead->next=p->next;
        p->next=NULL;
        //更新任務數量
        pool->tasknum--;
        //printf("%ld執行緒正在執行任務\n",pthread_self());
        //解鎖
        pthread_mutex_unlock(&(pool->threadmutex));
        (p->taskp)(p->taskarg);
        free(p);
    }
}
//初始化執行緒池結構體
struct threadpool *thread_init(int num)
{
    struct threadpool *mythread=malloc(sizeof(struct threadpool));//申請堆空間
    mythread->threadnum=num;
    mythread->threadid=malloc(num*sizeof(pthread_t));
    //初始化鏈表的表頭
    mythread->taskhead=myhead;
    //鎖初始化
    pthread_mutex_init(&(mythread->threadmutex),NULL);
    //條件變數初始化
    pthread_cond_init(&(mythread->threadcond),NULL);
    mythread->tasknum=0;
    mythread->threadflag=true;
    for(int i=0;i<num;i++)
        pthread_create(&(mythread->threadid[i]),NULL,routine,mythread);
    return mythread;
}
//添加任務函式
int add_task(void *(*p)(void *),void *newarg,struct threadpool *pool)
{
    //找到尾部
    struct tasklist *q=pool->taskhead;
    while(q->next!=NULL)
        q=q->next;
    //準備新結點
    struct tasklist *newnode=malloc(sizeof(struct tasklist));
    newnode->taskp=p;
    newnode->taskarg=newarg;
    newnode->next=NULL;
    
    //上鎖
    pthread_mutex_lock(&(pool->threadmutex));
    //尾插
    q->next=newnode;
    //更新任務數量
    pool->tasknum++;
    pthread_mutex_unlock(&(pool->threadmutex));
    //喚醒條件
    pthread_cond_signal(&(pool->threadcond));
    return 0;    
}
/***************************************************************************/
//                                功能函式
/***************************************************************************/
//主目錄名
void *mycopyname(void *myarg)
{
    struct copypath *mypath=(struct copypath *)myarg;
    char fpath[15];    //求出主目錄的名字
    char temp[100];
    strcpy(temp,mypath->oldpath);
    char *p=strtok(temp,"/");
    //獲取檔案名
    while(p!=NULL)
    {
        bzero(fpath,15);
        strcpy(fpath,p);
        p=strtok(NULL,"/");
    }
    strcpy(((struct copypath *)myarg)->target,fpath);
}
//普通檔案復制
void *myregcp(void *myarg)
{
    struct copypath *mypath=(struct copypath *)myarg;
    
    //系統IO的復制
    int fd1,fd2;
    fd1=open(mypath->oldpath,O_RDONLY);
    fd2=open(mypath->newpath,O_CREAT|O_TRUNC|O_RDWR,0777);
    if(fd1==-1)
    {
        perror("打開1失敗\n");
        return NULL;
    }
    if(fd2==-1)
    {
        perror("打開2失敗\n");
        return NULL;
    }
    char buf[SIZE];
    int nread,nwrite;
    while(1)
    {
        bzero(buf,SIZE);
        nread=read(fd1,buf,SIZE);
        //cs=cs+nread;
        if(nread==0)
            break;
        cs=cs+nread;
        write(fd2,buf,nread);
    }
    close(fd1);
    close(fd2);    
    return NULL;    
}
//遍歷讀目錄
int myreaddir(struct copypath *pp,struct threadpool *pool)
{
    DIR *dirp=opendir(pp->oldpath);
    if(dirp==NULL)
    {
        perror("失敗:\n");
        return -1;
    }
    struct dirent *p;    
    while((p=readdir(dirp))!=NULL)
    {    
        if(p->d_type==DT_REG)        //普通檔案
        {
            struct copypath *mypath=malloc(sizeof(struct copypath));
            sprintf(mypath->oldpath,"%s/%s",pp->oldpath,p->d_name);
            sprintf(mypath->newpath,"%s/%s",pp->newpath,p->d_name);
            add_task(myregcp,mypath,pool);    //實作
        }
        if(p->d_type==DT_DIR)        //檔案夾
        {                
            if(strcmp(p->d_name,".")!=0 && strcmp(p->d_name,"..")!=0)
            {    
                struct copypath *mydirpath=malloc(sizeof(struct copypath));
                sprintf(mydirpath->oldpath,"%s/%s",pp->oldpath,p->d_name);
                sprintf(mydirpath->newpath,"%s/%s",pp->newpath,p->d_name);
                mkdir(mydirpath->newpath,0777);
                myreaddir(mydirpath,pool);
            }
        }
    }
    closedir(dirp);
    return 1;
}
//遞回算位元組數
int size_sum(struct copypath *pp)
{
    DIR *dirp=opendir(pp->oldpath);
    if(dirp==NULL)
    {
        perror("失敗:\n");
        return -1;
    }
    struct dirent *p;
    struct stat info;
    while((p=readdir(dirp))!=NULL)
    {    
        if(p->d_type==DT_REG)        //普通檔案
        {
            struct copypath *mypath=malloc(sizeof(struct copypath));
            sprintf(mypath->oldpath,"%s/%s",pp->oldpath,p->d_name);
            //計算位元組數
            stat(mypath->oldpath,&info);
            s=s+info.st_size;
        }
        if(p->d_type==DT_DIR)        //檔案夾
        {                
            if(strcmp(p->d_name,".")!=0 && strcmp(p->d_name,"..")!=0)
            {    
                struct copypath *mydirpath=malloc(sizeof(struct copypath));
                sprintf(mydirpath->oldpath,"%s/%s",pp->oldpath,p->d_name);
                size_sum(mydirpath);
            }
        }
    }
    closedir(dirp);
    return 1;
}
//實作進度條
void *pro_bar(void *myarg)
{
    int i,j=0;
    float k,num;
    printf("進度:");
    while(1)
    {
        j=k;
        num=(float)cs;        //正在復制位元組數
        k=(num/s)*20;        //
        k=(int)k;        
        if(k-j>=1)
        {
            for(i=0;i<k-j;i++)        
            {                
                printf("\033[1;31;42m | \033[0m");
            }
            fflush(NULL);
        }
        usleep(10000);
        if(s==cs)
        {
            printf("\033[1;31;42m | \033[0m");
            fflush(NULL);
            usleep(200);
            break;
        }            
    }
    printf("\n任務完成\n");
    return NULL;
}
//lseep計時
void *my_time(void *myarg)
{
    while(1)
    {
        sleep(1);
        tm++;
        if(s==cs)
        {
            break;
        }
    }
}
//顯示選擇拷貝型別界面
int showdow()
{
    int n;
    printf("**********************\n");
    printf(" 請輸入你要拷貝的檔案 \n");
    printf("   1.復制全部檔案;    \n");
    printf("   2.選擇型別復制;    \n");
    printf("   3.原目錄檔案樹;    \n");
    printf("   4.查找某個檔案;   \n");
    printf("   5.洗掉某個檔案.    \n");
    printf("**********************\n");
    scanf("%d",&n);
    return n;
}
//遞回讀取檔案型別的位元組數
int ftypesize_sum(struct copypath *pp,char *ftype)
{
    DIR *dirp=opendir(pp->oldpath);
    if(dirp==NULL)
    {
        perror("失敗:\n");
        return -1;
    }
    struct dirent *p;
    struct stat info;
    while((p=readdir(dirp))!=NULL)
    {    
        if(p->d_type==DT_REG)        //普通檔案
        {
            if(strstr(p->d_name,ftype)!=NULL)    //檔案型別
            {
                struct copypath *mypath=malloc(sizeof(struct copypath));
                sprintf(mypath->oldpath,"%s/%s",pp->oldpath,p->d_name);
                //計算位元組數
                stat(mypath->oldpath,&info);
                s=s+info.st_size;
            }            
        }
        if(p->d_type==DT_DIR)        //檔案夾
        {    
            if(strcmp(p->d_name,".")!=0 && strcmp(p->d_name,"..")!=0)
            {    
                struct copypath *mydirpath=malloc(sizeof(struct copypath));
                sprintf(mydirpath->oldpath,"%s/%s",pp->oldpath,p->d_name);
                ftypesize_sum(mydirpath,ftype);
            }
        }
    }
    closedir(dirp);
    return 1;    
}
//遞回讀取檔案型別的目錄
int myftyper(struct copypath *pp,struct threadpool *pool,char *ftype)
{
    DIR *dirp=opendir(pp->oldpath);
    if(dirp==NULL)
    {
        perror("失敗:\n");
        return -1;
    }
    struct dirent *p;
    while((p=readdir(dirp))!=NULL)
    {    
        if(p->d_type==DT_REG)        //普通檔案
        {
            if(strstr(p->d_name,ftype)!=NULL)
            {
                struct copypath *mypath=malloc(sizeof(struct copypath));
                sprintf(mypath->oldpath,"%s/%s",pp->oldpath,p->d_name);
                sprintf(mypath->newpath,"%s/%s",pp->newpath,p->d_name);
                add_task(myregcp,mypath,pool);    //實作
            }
        }
        if(p->d_type==DT_DIR)        //檔案夾
        {                
            if(strcmp(p->d_name,".")!=0 && strcmp(p->d_name,"..")!=0)
            {    
                struct copypath *mydirpath=malloc(sizeof(struct copypath));
                sprintf(mydirpath->oldpath,"%s/%s",pp->oldpath,p->d_name);
                sprintf(mydirpath->newpath,"%s/%s",pp->newpath,p->d_name);
                mkdir(mydirpath->newpath,0777);
                myftyper(mydirpath,pool,ftype);
            }
        }
    }
    closedir(dirp);
    return 1;
}
//樹實作
void dirtree(char dirpath[],int level)
{
    int i;
    char *dirname=NULL;
    int dirlen;
    DIR *dp=opendir(dirpath);
    if(dp==NULL)
    {
        perror("失敗:\n");
        return;
    }
    struct dirent *ep;
    while((ep=readdir(dp))!=NULL)
    {
        if(strncmp(ep->d_name, ".", 1) == 0)
            continue;
        for(i=0;i<level;i++)
        {
            printf("|");
            printf("     ");
        }
        printf("|--- ");
        printf("\033[1;32;40m %s \033[0m\n",ep->d_name);
        if(ep->d_type==DT_DIR)
        {
            //當前目錄長度
            dirlen=strlen(dirpath)+1;
            //備份
            dirname=(char *)malloc(dirlen);
            memset(dirname,0,dirlen);
            memcpy(dirname,dirpath,dirlen);
            
            strcat(dirpath,"/");
            strcat(dirpath,ep->d_name);
            dirtree(dirpath,level+1);        //遞回實作樹效果
            //恢復之前的目錄名
            memcpy(dirpath,dirname,dirlen);
            free(dirname);            
            dirname = NULL;
        }
    }    
    closedir(dp);
}

//遞回查找相似檔案-查找檔案
int sc_file(struct copypath *pp,char *filename)
{
    DIR *dirp=opendir(pp->oldpath);
    if(dirp==NULL)
    {
        perror("失敗:\n");
        return -1;
    }
    struct dirent *p;
    while((p=readdir(dirp))!=NULL)
    {    
        if(p->d_type==DT_REG)        //普通檔案
        {
            if(strstr(p->d_name,filename)!=NULL)    //檔案型別
            {
                struct copypath *mypath=malloc(sizeof(struct copypath));
                sprintf(mypath->oldpath,"%s/%s",pp->oldpath,p->d_name);
                printf("已找到檔案路徑:%s\n",mypath->oldpath);
                free(mypath);
            }            
        }
        if(p->d_type==DT_DIR)        //檔案夾
        {    
            if(strcmp(p->d_name,".")!=0 && strcmp(p->d_name,"..")!=0)
            {    
                if(strstr(p->d_name,filename)!=NULL)    //檔案型別
                {
                    struct copypath *mypath1=malloc(sizeof(struct copypath));
                    sprintf(mypath1->oldpath,"%s/%s",pp->oldpath,p->d_name);
                    printf("已找到檔案路徑:%s\n",mypath1->oldpath);
                    free(mypath1);
                }
                struct copypath *mydirpath=malloc(sizeof(struct copypath));
                sprintf(mydirpath->oldpath,"%s/%s",pp->oldpath,p->d_name);
                sc_file(mydirpath,filename);
            }
        }
    }
    closedir(dirp);
    return 1;    
}
//洗掉--檔案\檔案夾
int alldet(struct copypath *pp)
{
    DIR *dirp=opendir(pp->oldpath);
    struct dirent *p;
    while((p=readdir(dirp))!=NULL)
    {    
        if(p->d_type==DT_REG)        //普通檔案
        {            
            struct copypath *mypath=malloc(sizeof(struct copypath));
            sprintf(mypath->oldpath,"%s/%s",pp->oldpath,p->d_name);
            remove(mypath->oldpath);            
        }
        if(p->d_type==DT_DIR)        //檔案夾
        {    
            if(strcmp(p->d_name,".")!=0 && strcmp(p->d_name,"..")!=0)
            {            
                struct copypath *mydirpath=malloc(sizeof(struct copypath));
                sprintf(mydirpath->oldpath,"%s/%s",pp->oldpath,p->d_name);
                alldet(mydirpath);
                rmdir(mydirpath->oldpath);
            }
        }
    }
    closedir(dirp);
    rmdir((pp->oldpath));
    return 1;    
}
/***************************************************************************/

/***************************************************************************/
//                                簡化主程式
/***************************************************************************/
int simcopy_all(struct threadpool *mypool)    //簡化主程式--復制全部
{    
    tm=s=cs=0;
    struct copypath paths;        //新舊路徑結構體
    printf("請輸入源檔案\n");
    scanf("%s",paths.oldpath);
    printf("請輸入目標檔案\n");
    scanf("%s",paths.newpath);
    mycopyname(&paths);
    sprintf(paths.newpath,"%s/%s",paths.newpath,paths.target);
    mkdir(paths.newpath,0777);
    size_sum(&paths);        //計算位元組數
    usleep(20);
    printf("總位元組數:%ld\n",s);
    add_task(my_time,NULL,mypool);
    add_task(pro_bar,NULL,mypool);
    myreaddir(&paths,mypool);
}
void simcopy(struct threadpool *mypool)        //簡化主程式--按檔案型別復制
{
    tm=s=cs=0;
    char ftype[6];            //檔案型別變數
    struct copypath paths;        
    printf("請輸入源檔案\n");
    scanf("%s",paths.oldpath);
    printf("請輸入目標檔案\n");
    scanf("%s",paths.newpath);
    mycopyname(&paths);
    sprintf(paths.newpath,"%s/%s",paths.newpath,paths.target);
    mkdir(paths.newpath,0777);
    printf("請輸入要復制的檔案型別,如.txt等\n");    
    scanf("%s",ftype);
    ftypesize_sum(&paths,ftype);        
    printf("總位元組數:%ld\n",s);
    usleep(20);
    add_task(my_time,NULL,mypool);
    add_task(pro_bar,NULL,mypool);
    myftyper(&paths,mypool,ftype);
}
void simtree()                                //簡化主程式--檔案樹
{
    char direntName[256];
    struct copypath paths;
    printf("請輸入源檔案\n");
    scanf("%s",paths.oldpath);
    memset(direntName, 0, sizeof(direntName));
    strcat(direntName, paths.oldpath);
    printf("%s\n",paths.oldpath);
    dirtree(direntName, 0);
}
void myscfile()                                //簡化主程式--查找
{    
    char fname[256];
    struct copypath paths;
    printf("請輸入查找檔案夾名\n");
    scanf("%s",paths.oldpath);
    printf("請輸入要查找的檔案名\n");
    scanf("%s",fname);
    sc_file(&paths,fname);
    usleep(10);
}
void mydel()                                //簡化主程式--洗掉
{
    tm=s=cs=0;
    char delfile[100];
    struct copypath paths;
    printf("請輸入要洗掉的檔案夾\n");
    scanf("%s",paths.oldpath);
    size_sum(&paths);        //計算位元組數
    printf("size is: %ld\n",s);
    alldet(&paths);
    usleep(10);
}
void endshow()                                //簡化主程式--結束
{
    printf("請輸入          \n");
    printf("    1--繼續     \n");
    printf("    2--退出     \n");
    scanf("%d",&flag);
}
/***************************************************************************/
//銷毀執行緒池
int pool_destroy(struct threadpool *pool)
{
    int i;
    //改變標志位,讓執行緒退出死回圈
    pool->threadflag=false;
    //喚醒所有執行緒
    pthread_cond_broadcast(&(pool->threadcond));
    //回收所有執行緒
    for(i=0;i<pool->threadnum;i++)
    {
        pthread_join(pool->threadid[i],NULL);
        //printf("%ld執行緒已被回收\n",pool->threadid[i]);
    }
    return 0;
}

int main()
{         
    struct copypath paths;
    while(1)
    {
        flag=0;
        system("clear");                
        myhead=task_init();            //初始化任務鏈表的表頭        
        struct threadpool *mypool=thread_init(10);        //創建并初始化執行緒池
        int ret=showdow();    
        switch(ret)
        {
            case 1:                        //拷貝全部
                simcopy_all(mypool);                
                pool_destroy(mypool);    //執行緒池的銷毀
                printf("拷貝花費:%d seconds\n",tm);
                break;
            case 2:                        //拷貝部分
                simcopy(mypool);
                pool_destroy(mypool);
                printf("拷貝花費:%d seconds\n",tm);
                break;
            case 3:                        //顯示檔案樹                
                simtree();
                break;
            case 4:                        //查找某個檔案--顯示相似的檔案
                myscfile();
                break;
            case 5:                        //洗掉某個檔案夾
                mydel();                
                printf("delete done\n");
                break;
            default:
                break;
        }
        endshow();        
        if(flag==1)
            continue;
        else if(flag==2)
            break;
    }
    system("clear");
    usleep(20);
    return 0;
}

 

 

有什么建議,歡迎聯系,郵箱:[email protected]

轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/3559.html

標籤:Linux

上一篇:Linux top詳解

下一篇:虛擬化技術之kvm管理工具virsh常用基礎命令(一)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • CA和證書

    1、在 CentOS7 中使用 gpg 創建 RSA 非對稱密鑰對 gpg --gen-key #Centos上生成公鑰/密鑰對(存放在家目錄.gnupg/) 2、將 CentOS7 匯出的公鑰,拷貝到 CentOS8 中,在 CentOS8 中使用 CentOS7 的公鑰加密一個檔案 gpg -a ......

    uj5u.com 2020-09-10 00:09:53 more
  • Kubernetes K8S之資源控制器Job和CronJob詳解

    Kubernetes的資源控制器Job和CronJob詳解與示例 ......

    uj5u.com 2020-09-10 00:10:45 more
  • VMware下安裝CentOS

    VMware下安裝CentOS 一、軟硬體準備 1 Centos鏡像準備 1.1 CentOS鏡像下載地址 下載地址 1.2 CentOS鏡像下載程序 點擊下載地址進入如下圖的網站,選擇需要下載的版本,這里選擇的是Centos8,點擊如圖所示。 決定選擇Centos8后,選擇想要的鏡像源進行下載,此 ......

    uj5u.com 2020-09-10 00:12:10 more
  • 如何使用Grep命令查找多個字串

    如何使用Grep 命令查找多個字串 大家好,我是良許! 今天向大家介紹一個非常有用的技巧,那就是使用 grep 命令查找多個字串。 簡單介紹一下,grep 命令可以理解為是一個功能強大的命令列工具,可以用它在一個或多個輸入檔案中搜索與正則運算式相匹配的文本,然后再將每個匹配的文本用標準輸出的格式 ......

    uj5u.com 2020-09-10 00:12:28 more
  • git配置http代理

    git配置http代理 經常遇到克隆 github 慢的問題,這里記錄一下幾種配置 git 代理的方法,解決 clone github 過慢。 目錄 git配置代理 git單獨配置github代理 git配置全域代理 配置終端環境變數 git配置代理 主要使用 git config 命令 git單獨 ......

    uj5u.com 2020-09-10 00:12:33 more
  • Linux npm install 裝包時提示Error EACCES permission denied解

    npm install 裝包時提示Error EACCES permission denied解決辦法 ......

    uj5u.com 2020-09-10 00:12:53 more
  • Centos 7下安裝nginx,使用yum install nginx,提示沒有可用的軟體包

    Centos 7下安裝nginx,使用yum install nginx,提示沒有可用的軟體包。 18 (flaskApi) [root@67 flaskDemo]# yum -y install nginx 19 已加載插件:fastestmirror, langpacks 20 Loading ......

    uj5u.com 2020-09-10 00:13:13 more
  • Linux查看服務器暴力破解ssh IP

    在公網的服務器上經常遇到別人爆破你服務器的22埠,用來挖礦或者干其他嘿嘿嘿的事情~ 這種情況下正確的做法是: 修改默認ssh的22埠 使用設定密鑰登錄或者白名單ip登錄 建議服務器密碼為復雜密碼 創建普通用戶登錄服務器(root權限過大) 建立堡壘機,實作統一管理服務器 統計爆破IP [root ......

    uj5u.com 2020-09-10 00:13:17 more
  • CentOS 7系統常見快捷鍵操作方式

    Linux系統中一些常見的快捷方式,可有效提高操作效率,在某些時刻也能避免操作失誤帶來的問題。 ......

    uj5u.com 2020-09-10 00:13:31 more
  • CentOS 7作業系統目錄結構介紹

    作業系統存在著大量的資料檔案資訊,相應檔案資訊會存在于系統相應目錄中,為了更好的管理資料資訊,會將系統進行一些目錄規劃,不同目錄存放不同的資源。 ......

    uj5u.com 2020-09-10 00:13:35 more
最新发布
  • vim的常用命令

    Vim的6種基本模式 1. 普通模式在普通模式中,用的編輯器命令,比如移動游標,洗掉文本等等。這也是Vim啟動后的默認模式。這正好和許多新用戶期待的操作方式相反(大多數編輯器默認模式為插入模式)。 2. 插入模式在這個模式中,大多數按鍵都會向文本緩沖中插入文本。大多數新用戶希望文本編輯器編輯程序中一 ......

    uj5u.com 2023-04-20 08:43:21 more
  • vim的常用命令

    Vim的6種基本模式 1. 普通模式在普通模式中,用的編輯器命令,比如移動游標,洗掉文本等等。這也是Vim啟動后的默認模式。這正好和許多新用戶期待的操作方式相反(大多數編輯器默認模式為插入模式)。 2. 插入模式在這個模式中,大多數按鍵都會向文本緩沖中插入文本。大多數新用戶希望文本編輯器編輯程序中一 ......

    uj5u.com 2023-04-20 08:42:36 more
  • docker學習

    ###Docker概述 真實專案部署環境可能非常復雜,傳統發布專案一個只需要一個jar包,運行環境需要單獨部署。而通過Docker可將jar包和相關環境(如jdk,redis,Hadoop...)等打包到docker鏡像里,將鏡像發布到Docker倉庫,部署時下載發布的鏡像,直接運行發布的鏡像即可。 ......

    uj5u.com 2023-04-19 09:26:53 more
  • 設定Windows主機的瀏覽器為wls2的默認瀏覽器

    這里以Chrome為例。 1. 準備作業 wsl是可以使用Windows主機上安裝的exe程式,出于安全考慮,默認情況下改功能是無法使用。要使用的話,終端需要以管理員權限啟動。 我這里以Windows Terminal為例,介紹如何默認使用管理員權限打開終端,具體操作如下圖所示: 2. 操作 wsl ......

    uj5u.com 2023-04-19 09:25:49 more
  • docker學習

    ###Docker概述 真實專案部署環境可能非常復雜,傳統發布專案一個只需要一個jar包,運行環境需要單獨部署。而通過Docker可將jar包和相關環境(如jdk,redis,Hadoop...)等打包到docker鏡像里,將鏡像發布到Docker倉庫,部署時下載發布的鏡像,直接運行發布的鏡像即可。 ......

    uj5u.com 2023-04-19 09:19:04 more
  • Linux學習筆記

    IP地址和主機名 IP地址 ifconfig可以用來查詢本機的IP地址,如果不能使用,可以通過install net-tools安裝。 Centos系統下ens33表示主網卡;inet后表示IP地址;lo表示本地回環網卡; 127.0.0.1表示代指本機;0.0.0.0可以用于代指本機,同時在放行設 ......

    uj5u.com 2023-04-18 06:52:01 more
  • 解決linux系統的kdump服務無法啟動的問題

    問題:專案麒麟系統服務器的kdump服務無法啟動,沒有相關日志無法定位問題。 1、查看服務狀態是關閉的,重啟系統也無法啟動 systemctl status kdump 2、修改grub引數,修改“crashkernel”為“512M(有的機器數值太大太小都會導致報錯,建議從128M開始試,或者加個 ......

    uj5u.com 2023-04-12 09:59:50 more
  • 解決linux系統的kdump服務無法啟動的問題

    問題:專案麒麟系統服務器的kdump服務無法啟動,沒有相關日志無法定位問題。 1、查看服務狀態是關閉的,重啟系統也無法啟動 systemctl status kdump 2、修改grub引數,修改“crashkernel”為“512M(有的機器數值太大太小都會導致報錯,建議從128M開始試,或者加個 ......

    uj5u.com 2023-04-12 09:59:01 more
  • 你是不是暴露了?

    作者:袁首京 原創文章,轉載時請保留此宣告,并給出原文連接。 如果您是計算機相關從業人員,那么應該經歷不止一次網路安全專項檢查了,你肯定是收到過資訊系統技術檢測報告,要求你加強風險監測,確保你提供的系統服務堅實可靠了。 沒檢測到問題還好,檢測到問題的話,有些處理起來還是挺麻煩的,尤其是線上正在運行的 ......

    uj5u.com 2023-04-05 16:52:56 more
  • 細節拉滿,80 張圖帶你一步一步推演 slab 記憶體池的設計與實作

    1. 前文回顧 在之前的幾篇記憶體管理系列文章中,筆者帶大家從宏觀角度完整地梳理了一遍 Linux 記憶體分配的整個鏈路,本文的主題依然是記憶體分配,這一次我們會從微觀的角度來探秘一下 Linux 內核中用于零散小記憶體塊分配的記憶體池 —— slab 分配器。 在本小節中,筆者還是按照以往的風格先帶大家簡單 ......

    uj5u.com 2023-04-05 16:44:11 more