c - 在 C 中一次运行恒定数量的线程

标签 c multithreading pthreads

我正在尝试使用 pthreads 将文件从一个目录复制到另一个目录。每个线程只负责复制一个文件。最大线程数通过命令行参数指定。

我想做的是,如果当前线程数小于最大线程数,则创建一个线程来完成工作。否则,等待当前线程,当其中一个线程完成时,减少当前线程的数量。

我不知道如何在不阻塞主线程的情况下通过 pthread_join 等待线程。

这是我目前所拥有的:

#include <stdlib.h>
#include <stdio.h>
#include <dirent.h>
#include <stdlib.h>
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>

#define MAXNAME 80
#define R_FLAGS O_RDONLY
#define W_FLAGS (O_WRONLY | O_CREAT)
#define W_PERMS (S_IRUSR | S_IWUSR)
#define KILOBYTE 0.001

void *copyfilepass(void *arg);

int main(int argc, char* argv[]){

    int num_threads;        //number of threads to execute in parallel
    int cur_threads = 0;    //number of threads currently executing
    char filename[MAXNAME]; //will temporarily hold the file name
    DIR* source;            //pointer to the source directory
    DIR* dest;              //pointer to the destination directory
    struct dirent* dentry;  //pointer to the internal structure of the source directory
    struct stat fst;        //stats for each file in a directory
    int error;
    void *status;

    //***BEGIN ERROR CHECKING***

    if (argc != 4) {
        fprintf(stderr, "Usage: %s sourceDir destDir numThreads\n", argv[0]);
        return 1; 
    } 

    //check if source directory name is too long
    if ( snprintf(filename, MAXNAME, "%s", argv[1]) == MAXNAME ) {
        fprintf(stderr, "Source directory name %s too long\n", argv[1]); 
        return 1;
    }
    //check if destination directory name is too long
    if ( snprintf(filename, MAXNAME, "%s", argv[2]) == MAXNAME ) {
        fprintf(stderr, "Source directory name %s too long\n", argv[2]); 
        return 1;
    }

    //check if we can successfully open the source directory
    if( (source = opendir(argv[1])) == NULL ) {
        fprintf(stderr, "Error opening source directory %s\n", argv[1]); 
        return 1;
    }

    //check if we can successfully open the destination directory
    if( (dest = opendir(argv[2])) == NULL ) {
        fprintf(stderr, "Error opening destination directory %s\n", argv[2]); 
        return 1;
    }

    //***END ERROR CHECKING***

    num_threads = atoi(argv[3]);

    while( (dentry = readdir(source)) != NULL ){
        //source path
        char* path = (char*)malloc(sizeof(char) * (strlen(dentry->d_name) + strlen(argv[1]) + 2)); //need '.' + '/' + '\0'
        sprintf(path, "%s%c%s", argv[1], '/', dentry->d_name);

        //destination path
        char* dest_path = (char*)malloc(sizeof(char) * (strlen(dentry->d_name) + strlen(argv[2]) + 2)); //need '.' + '/' + '\0'
        sprintf(dest_path, "%s%c%s", argv[2], '/', dentry->d_name);

        if(!stat(path, &fst)){ //stat() return 0 if successful
            if(S_ISREG(fst.st_mode)){

                int args[3];
                pthread_t tid;

                if ( (args[0] = open(path, R_FLAGS)) == -1 ) {
                    fprintf(stderr, "Failed to open source file %s: %s\n", path, strerror(errno));
                    continue; 
                }
                if ( (args[1] = open(dest_path, W_FLAGS, W_PERMS)) == -1 ) {
                    fprintf(stderr, "Failed to open destination file %s: %s\n", dest_path, strerror(errno));
                    continue;
                }

                if(cur_threads < num_threads) {

                    ++cur_threads;

                    if ( (error = pthread_create((&tid), NULL, copyfilepass, args)) ) {
                        --cur_threads;
                        fprintf(stderr, "Failed to create thread: %s\n", strerror(error));
                        tid = pthread_self();    /* cannot be value for new thread */
                    }

                    printf("file: %.03fKB %s\n", (fst.st_size * KILOBYTE), path);

                }

            }
        }
    }
    //close directory
    closedir(source);

    return 0;

}

最佳答案

比产生和收获线程更好的是在开始时只创建一个固定大小的池并让它们全部从工作队列中使用。这将减少开销并简化您的代码。

顺便说一下,使用线程来解决这个问题可能不会提高性能,这取决于您正在操作的文件系统。值得深思。

关于c - 在 C 中一次运行恒定数量的线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39939326/

相关文章:

python - Windows Python 错误的交叉编译

c - unicode 排序规则 NIF 运行速度比纯 Erlang 实现慢

multithreading - 具有后台线程的WCF NetTCP

java - 如何通过多线程避免Oracle中的重复插入

c - ubuntu 上的 sem_init 使用 C 语言

c - golang 对共享内存的支持

multithreading - 在Vec上实现并行/多线程合并排序

客户端读取另一个文件后没有读取任何数据

c - 埃拉托色尼筛法 Pthread 实现 : thread number doesn't affect computation time

c - 程序写入socket后自动关闭