多线程统计文件数量有误-已更改

目录

一、输出文件有误的代码

二、更改后的代码


一、输出文件有误的代码

/**
 * @file mthread2.c
 * @brief 多线程文件搜索
 * @author zxy
 * @contact 
 * @created 2023-7-16
 * @modified 2023-7-17
**/
#include <stdio.h>
#include <dirent.h>
#include <pthread.h>
#include <string.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/stat.h>

#define MAX_THREADS 64
#define MAX_PATH_LENGTH 1024

int total_file_count = 0;
int total_folder_count = 0;

//线程传入参数
/* struct ThreadArgs 
{
    char path[MAX_PATH_LENGTH];//路径
}; */

char* path;

//创建互斥锁变量
pthread_mutex_t mutex;
 
void* search_files_and_directories(void* arg) //线程的入口点
{
    struct stat filestat;
    //强制类型转换:将 void* 类型的参数 arg 转换为 struct ThreadArgs* 类型的指针 args
    //struct ThreadArgs* args = (struct ThreadArgs*)arg;
    
   // char* path = path;
   // int* file_count = &(args->file_count);
   // int* folder_count = &(args->folder_count);
 
    DIR* directory;
    /*
    声明了一个指向目录的指针 directory。
    用于保存打开的目录流的信息,方便后续的操作。
    */
    struct dirent* entry;
    /*
    声明了一个指向目录中条目(文件或子目录)的指针 entry。
    struct dirent 是一个结构体类型,用于保存目录中条目的信息,例如名称、类型等。
    */
 
    directory = opendir(path);
    if (NULL == directory) {
        printf("Unable to open directory: %s\n", path);
        pthread_exit(NULL);//终止“当前线程”
    }
 
    
    while (NULL != (entry = readdir(directory))) 
    {
        
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) 
        {
            continue;
        }

        char sub_path[MAX_PATH_LENGTH];
        snprintf(sub_path, sizeof(sub_path), "%s/%s", path, entry->d_name);//整合,路径+属性

        // 获取文件/文件夹信息
        if (stat(sub_path, &filestat) < 0) {
            printf("无法获取文件/文件夹信息:%s\n", sub_path);
            continue;
        }

        if (S_ISDIR(filestat.st_mode)) 
        
        {
            pthread_mutex_lock(&mutex);
            // 如果是文件夹,则增加文件夹数量,并递归调用统计子目录下的文件和文件夹数量
            total_folder_count++;
            pthread_mutex_unlock(&mutex);
        }
        else 
        {
            pthread_mutex_lock(&mutex);
            // 如果是文件,则增加文件数量
            total_file_count++;
            pthread_mutex_unlock(&mutex);
        }
    }
 
    closedir(directory);
 
    pthread_exit(NULL);
}
 
int main(int argc, char* argv[])
//argc:命令行参数个数 argv:指向字符指针数组的指针,每个字符指针指向一个命令行参数字符串。注意最后一个是一个空指针代表参数列表的结束。
{
    if (argc != 2) 
    {
        printf("Usage: %s <directory>\n", argv[0]);
        return 0;
    }
 
    path = argv[1];
 
    //初始化互斥锁
    pthread_mutex_init(&mutex,NULL);

    struct timeval start;
    // 获取程序运行开始时间
    gettimeofday(&start, NULL);//start 时间值; NULL,时区值

    // 创建线程数组和线程参数数组
    pthread_t threads[MAX_THREADS];//线程数组
    
    //pthread_t是一个数据类型,表示线程标识符(线程ID)
    
    //struct ThreadArgs thread_args[MAX_THREADS];//线程参数数组
 
    // 遍历,初始化线程参数数组
    /* for (int i = 0; i < MAX_THREADS; i++) {
        strcpy(thread_args[i].path, path); // 设置搜索路径
    } */
 
    // 创建多个线程来搜索文件和文件夹
    for (int i = 0; i < MAX_THREADS; i++) {
        pthread_create(&threads[i], NULL, search_files_and_directories, NULL);
        /*
        pthread_create:用于创建线程,并将其与一个线程函数关联起来
        int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void* (*start_routine)(void*), void* arg)
        threat:指向pthread_类型的指针,用于存储线程ID
        attr:表示线程的属性,通常使用NULL表示使用默认属性
        start_routine:线程要执行的函数指针。该函数的返回类型和参数必须为void*
        arg:传递给线程函数的参数
        */
    }
 
    // 等待线程完成,汇总文件和文件夹数量
    for (int i = 0; i < MAX_THREADS; i++) {
        pthread_join(threads[i], NULL);
        /*
        pthread_join:用于等待制定的线程结束
        int pthread_join(pthread_t thread, void** retval)
        thread:要等待的线程的ID
        retval:一个双重指针,用于存储被等待线程函数的返回值
        */
    }

    pthread_mutex_destroy(&mutex);
 
    // 获取程序运行结束时间
    struct timeval end;
    gettimeofday(&end, NULL);

    // 计算程序的运行时间(单位:微秒)
    long duration = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_usec - start.tv_usec);

    // 获取程序的占用内存大小(单位:字节)
    struct rusage usage;
    getrusage(RUSAGE_SELF, &usage);
    long memory_usage = usage.ru_maxrss;

    // 输出统计结果和程序运行时间、内存使用情况
    printf("Total number of files: %d\n", total_file_count);
    printf("Total number of folders: %d\n", total_folder_count);
    printf("Program duration: %ld microseconds\n", duration);
    printf("Memory usage: %ld bytes\n", memory_usage);
 
    return 0;
}

二、更改后的代码

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <dirent.h>
#include <string.h>

#define MAX_THREADS 64

// 定义全局变量
int totalFiles = 0;
int totalDirs = 0;
pthread_mutex_t mutex;

// 定义任务结构体
typedef struct {
    char* path;
} Task;

// 递归遍历目录并统计文件和文件夹数量的函数
void countFilesAndDirs(const char* path) {
    DIR* dir;
    struct dirent* entry;
    char fullPath[256];

    // 打开目录
    dir = opendir(path);
    if (dir == NULL) {
        return;
    }

    // 遍历目录中的每个项
    while ((entry = readdir(dir)) != NULL) {
        // 排除当前目录和上一级目录
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
            continue;
        }

        // 构建完整路径
        snprintf(fullPath, sizeof(fullPath), "%s/%s", path, entry->d_name);

        // 如果是文件夹,则递归调用该函数
        if (entry->d_type == DT_DIR) {
            countFilesAndDirs(fullPath);
            pthread_mutex_lock(&mutex);
            totalDirs++;
            pthread_mutex_unlock(&mutex);
        }

        // 如果是文件,则增加文件计数
        if (entry->d_type == DT_REG) {
            pthread_mutex_lock(&mutex);
            totalFiles++;
            pthread_mutex_unlock(&mutex);
        }
    }

    // 关闭目录
    closedir(dir);
}

// 线程函数
void* threadFunction(void* arg) {
    Task* task = (Task*) arg;
    countFilesAndDirs(task->path);
    free(task);
    return NULL;
}

int main(int argc, char* argv[]) {
    pthread_t threads[MAX_THREADS];
    int numThreads;
    int i;

    if (argc != 2) {
        printf("Usage: %s directory_path\n", argv[0]);
        return 1;
    }

    if (pthread_mutex_init(&mutex, NULL) != 0) {
        printf("Mutex initialization failed.\n");
        return 1;
    }

    // 创建多个线程进行处理
    numThreads = argc < MAX_THREADS ? argc - 1 : MAX_THREADS;
    for (i = 0; i < numThreads; i++) {
        Task* task = (Task*) malloc(sizeof(Task));
        task->path = argv[i + 1];
        pthread_create(&threads[i], NULL, threadFunction, (void*) task);
    }

    // 等待线程结束
    for (i = 0; i < numThreads; i++) {
        pthread_join(threads[i], NULL);
    }

    pthread_mutex_destroy(&mutex);

    // 打印结果
    printf("Total files: %d\n", totalFiles);
    printf("Total directories: %d\n", totalDirs);

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值