2012-03-21 90 views
1

我正在做我的功课,我要完成的是计算给定目录的目录和文件,但是我发现每个目录都应该与我的过程的另一个线程一起计数,这就是我到目前为止有:加入线程混淆

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

您的问题最近的原因是dir->nameNULL在创建的附加线程,因为opendir(curr->d_name);失败。这是因为目录curr->d_name不是绝对路径名 - opendir()将在当前工作目录中查找您要打开的目录,但该目录实际上位于您当前正在处理的目录中。

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

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

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

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

非常有用,但是我无法进行此修改,但是我接受了这个想法并对代码进行了一些更改,现在我的原始帖子在“修改”标题下:) – 2012-03-21 16:14:02

1

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

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

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

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

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

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

希望这会有所帮助。