加入线程混乱

时间:2012-03-21 06:03:00

标签: c pthreads

我正在做我的作业,我要完成的是计算给定目录的目录和文件,但是我找到的每个目录都应该计入我的进程的另一个线程,这是我到目前为止:

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);

修改后的作用: 打印所有目录,但它确实给出了分段错误,而某些线程无法完成它的任务。

2 个答案:

答案 0 :(得分:2)

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

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

当您找到作为目录的目录条目时,您需要通过将"/"curr->d_name连接到正在处理的目录的路径名来构造路径名以传递给新线程。

请注意,您根本不需要dsp变量和telldir()的调用。如果您有一个有效的DIR *dir,则只需使用以下内容循环播放:

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

答案 1 :(得分:1)

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

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

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

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

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

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

希望这有帮助。