【问题标题】:Joining threads confusion加入线程混乱
【发布时间】:2012-03-22 00:12:42
【问题描述】:

我正在做我的功课,我必须完成的是计算给定目录的目录和文件,但是我找到的每个目录都应该与我的进程的另一个线程一起计算,这就是我到目前为止所拥有的:

void *dirCounter(void *param){
queue<pthread_t> queue;
dir_ptr dir = (dir_ptr)param;
dir->countDir = 0;
DIR* dirName = dir->name;
struct dirent *curr;
off_t dsp;
dsp= telldir(dirName);
while(dsp!= -1){
    curr = readdir(dirName);
    if(curr == NULL){
        break;
    }
    if(!strcmp(curr->d_name,".")|!strcmp(curr->d_name,"..")) {  //To avoid counting . and ..
        dsp = telldir(dirName); //Actual position asociated to the stream
        continue;   //Executes the beginning of the while
    }
    if(curr->d_type == DT_DIR){
        dir->countDir++; //counts directories in the first level
        //For each directory found, create another thread and add it to the queue:

        pthread_attr_t attr1;
        pthread_t tid1;
        pthread_attr_init(&attr1);
        dir_ptr par1 = (dir_ptr)malloc(sizeof(directorio));
        par1->name = opendir(curr->d_name);
        par1->countDir = par1->countFile = 0;
        pthread_create(&tid1,&attr1, dirCounter, par1);
        //queue.push(tid1);
    }
    if(curr->d_type == DT_REG){
        dir->countFile++; //Counts files
    }
    dsp = telldir(dirName);
}
//pthread_join(tid1, NULL);
//while(!queue.empty()){
    //pthread_join(queue.front(), NULL);
//  queue.pop();
//}
printf("Dirs: %d Files: %d\n", dir->countDir, dir->countFile);
pthread_exit(NULL); 
}

到目前为止,如果连接被注释,代码确实会计算“第一级”的当前文件和目录,然后它只是给出一个分段错误,如果该行未注释它只给出一个输出行,然后死于分段错误。 这个想法是每当我找到一个目录时创建一个线程,然后在最后将它们全部连接起来,创建一个半递归例程。

修改:

char str[256];
strcpy(str, "./");
strcat(str, curr->d_name);
//strcat(str, "\"");
puts(str);
par1->name = opendir(str);
par1->countDir = par1->countFile = 0;
pthread_create(&tid1,&attr1, dirCounter, par1);
queue.push(tid1);

修改后的作用: 打印所有目录,但是它确实给出了分段错误并且一些线程没有完成它的任务。

【问题讨论】:

    标签: c pthreads


    【解决方案1】:

    您的问题的直接原因是dir-&gt;name 在创建的其他线程中是NULL,因为opendir(curr-&gt;d_name); 失败。这是因为目录 curr-&gt;d_name 不是绝对路径名 - opendir() 将在 当前工作目录 中查找您要打开的目录,但该目录实际上在您的目录中'目前正在研究中。

    我建议不要将DIR * 值传递给线程,而只需传递目录的路径名,让线程自己执行opendir()。然后它应该测试返回值,并且只有在opendir() 返回非NULL 时才继续调用readdir()

    当您发现一个目录条目是一个目录时,您需要通过将"/"curr-&gt;d_name 连接到正在处理的目录的路径名上来构造一个路径名以传递给新线程。

    请注意,您根本不需要dsp 变量和对telldir() 的调用。如果你有一个有效的DIR *dir,你可以简单地循环它:

    while (curr = readdir(dir)) {
        /* Do something with curr */
    }
    

    【讨论】:

    • 非常有用,但是我无法进行此修改,但我接受了这个想法并对代码进行了一些更改,这些更改现在在我的原始帖子中的“修改”标题下:)
    【解决方案2】:

    我看到了一些错误。我不确定这是否可以解释您的崩溃。

    您为每个目录和相应的线程分配了一个“directorio”实例。但你永远不会释放它。内存泄漏。

    是打印整个文件系统的目录和文件的总数吗?或者只是每个目录的单个目录和文件计数?如果是前者,则您不会将结果添加备份。我什至建议让所有线程为 dirCount 和 fileCount 共享相同的整数指针。 (并使用锁来序列化访问或仅使用__sync_add_and_fetch)。您也可以只使用一组全局变量作为整数目录和文件计数。

    如果是后一种情况(每个线程打印它自己的子文件总和),只需传递一个目录名称(字符串)作为线程参数,并让线程使用堆栈外的局部变量作为计数器。 (线程会在传入的字符串上调用 opendir。它仍然需要释放传入的分配字符串。)

    您不需要将 pthread_attr_t 实例传递给 pthread_create。您可以将NULL作为第二个参数传递并获得相同的效果。

    您没有检查 pthread_create 的返回值。如果它失败(不太可能),那么 tid1 可能是一个垃圾值。

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2019-08-22
      • 2017-08-16
      • 1970-01-01
      • 1970-01-01
      • 2015-10-18
      • 2013-11-29
      • 1970-01-01
      • 2016-10-05
      • 1970-01-01
      相关资源
      最近更新 更多