用线程池实现目录文件拷贝

/ 0评 / 0

这是一个阶段性项目
整个程序实现的功能有
1.实现类tree命令让文件夹结构能够以树状图展示
2.实现对目录文件的拷贝
3.显示进度条
4.统计拷贝文件所用的时间
废话不多说,直接贴代码。

头文件“common.h”,把会用的头文件全都引入,这样就不用每次一个一个去写了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#ifndef __COMMON_H
#define __COMMON_H

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <strings.h>
#include <fcntl.h>
#include <time.h>
#include <stdbool.h>
#include <sys/wait.h>

// 目录
#include <dirent.h>

// 触摸屏
#include <linux/input.h>

//多线程
#include <pthread.h>

// 液晶屏
#include <sys/mman.h>
#include <linux/fb.h>
//共享内存
#include<sys/shm.h>

//消息队列
#include <sys/msg.h>
#include <signal.h>
//信号量
#include <sys/sem.h>
#include <sys/ipc.h>

#endif

一些宏定义

1
2
3
4
5
6
7
8
#ifndef LL_NODE_TYPE
#define LL_NODE_TYPE struct path
#endif

typedef LL_NODE_TYPE datatype;

long long allsize=0;//总文件大小
long long cpsize=0;//已拷贝文件大小

目录遍历的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
int myreaddir(char *srcdir,char *destdir,pthread_pool * pool)
{                  
    int ret;
    struct dirent *p;
        linklist head = init_list();//初始化一个链表用于存放原始路径和目标路径
    char sdir[257]={0};//不懂为啥定义为256会警告,说是可能会达到257,所以定义为了256
    char ddir[257]={0};//用来存放拼接好的路径
    //打开源文件夹递归读取里面内容
    DIR *mydir=opendir(srcdir);
    if(mydir==NULL)
    {
        perror("打开原目录失败!\n");
        return -1;
    }
   
    sprintf(ddir,"%s/%s",destdir,srcdir);//ddir=destdir+srcdir  PS:这里只针对相对路径,程序没有对绝对路径进行处理
    //新建目录文件夹
    ret=mkdir(ddir,0777);
    if(ret==-1)
    {
        perror("新建目录文件夹失败");
        printf("目录路径:%s\n",ddir);//调试用
        return -1;
    }
    while((p=readdir(mydir))!=NULL)
    {
        //排除掉 .和..
        if(strncmp(p->d_name,".",1)==0)
            continue;
        //判断读取的文件类型
        if(p->d_type==DT_DIR)  //目录
        {
            bzero(sdir,257);
            //拼接得到目录的完整路径
            sprintf(sdir,"%s/%s",srcdir,p->d_name); //原路径
            myreaddir(sdir,destdir,pool);//递归调用
           
        }
        else  //不是目录
        {
            struct path filepath;//用来存放原始路径以及目标路径的一个结构体
            bzero(sdir,257);        
            sprintf(sdir,"%s/%s",srcdir,p->d_name);//拼接原始路径
            sprintf(ddir,"%s/%s",ddir,p->d_name);//拼接目标路径
            strcpy(filepath.src,sdir);
            strcpy(filepath.dst,ddir);//给结构体成员赋值
            linklist newnode;//定义一个链表用来存放所有文件的路径
            newnode=new_node(filepath);//创建新节点
            insert_node(newnode,head);//尾插
            sprintf(ddir,"%s/%s",destdir,srcdir);
            addtask(cp_file,(void*)newnode,pool);//向线程池投放任务          
        }
    }
}

获取目录的大小
其实就是遍历累加,写的很繁琐,之前遍历目录就该一起做的,但是由于是遍历一个就拷贝一个,所以只能单独开一个函数来做了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
void size(char* dir)
{
    DIR *dp;
    struct dirent *entry;
    struct stat statbuf;
    if( (dp = opendir(dir)) == NULL )
    {
        fprintf(stderr, "cannot open directory: %s\n", dir);
        return;
    }
    chdir(dir);
    while( (entry = readdir(dp)) != NULL)
    {
        lstat(entry->d_name, &statbuf);
        if( S_ISDIR(statbuf.st_mode) )
        {
            if( strcmp(".", entry->d_name) == 0 || strcmp("..", entry->d_name) == 0 )
            continue;
            size(entry->d_name);
        }
        else
        {
            struct stat filesize;
            stat(entry->d_name,&filesize);
            allsize+=(filesize.st_size/1000);
        }

    }
    chdir("..");
    closedir(dp);
}

类tree的实现//效果不是太好 烂烂烂 比之前好点所以只是烂烂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
void printdir(char* dir, int depth)
{
    DIR *dp;
    struct dirent *entry;
    struct stat statbuf;
    if( (dp = opendir(dir)) == NULL )
    {
        fprintf(stderr, "cannot open directory: %s\n", dir);
        return;
    }
    chdir(dir);
    while( (entry = readdir(dp)) != NULL)
    {
        lstat(entry->d_name, &statbuf);
        if( S_ISDIR(statbuf.st_mode) )
        {
            if( strcmp(".", entry->d_name) == 0 || strcmp("..", entry->d_name) == 0 )
            continue;
            printf("%*s|__\033[1m\033[45;33m%s \033[0m\n", depth, " ", entry->d_name);//目录输出带颜色
            printdir(entry->d_name, depth+4);
        }
        else
        printf("%*s|__%s\n", depth, " ", entry->d_name);
    }
    chdir("..");
    closedir(dp);
}

剩下的就是线程池相关的了,写在写一篇吧。

发表评论

电子邮件地址不会被公开。 必填项已用*标注