【问题标题】:using threading and mutex locks to search directories使用线程和互斥锁搜索目录
【发布时间】:2017-11-26 20:13:05
【问题描述】:

我是线程新手,我相信我理解这个概念。由于锁是使用线程的必要工具,但(或至少对我而言)对如何使用感到困惑,我需要使用它们,但似乎无法正确使用它们。这里的想法是搜索目录以查找 CSV 文件。 (将在 CSV 上完成更多工作,但这与此处无关)我有一个算法可以在不使用线程的情况下搜索可以正常工作的目录。 (请记住,搜索目录是一种非常适合递归的任务,因为您需要搜索一个目录以找到另一个目录,当您找到新目录时,您要搜索该目录)因为我需要使用线程在查找新目录的每个实例上,我都设置了两次相同的算法。一旦在 main 中找到目录并调用函数(通过线程)来搜索找到的目录。同样,如果我在没有线程的情况下使用此方法,我的问题为零,但是通过线程,我发送给函数的参数将被覆盖。即使我锁定了整个功能,也会发生这种情况。显然我没有正确使用锁和线程,但是我要去哪里错了。我有测试目录来验证它是否正常工作。我在“。”中有 3 个目录。目录,然后是除此之外的子目录。它可以很好地找到前三个目录(在 main 中),然后当它将这些目录传递给线程函数时,它将搜索三个不同的时间,但通常不止一次搜索同一个目录。换句话说,路径名似乎被覆盖了。我会发布代码,这样你就可以看到我在做什么。我提前谢谢你。完整代码链接:sorter.h https://pastebin.com/0vQZbrmhsorter.c https://pastebin.com/9wd8aa74dirWorker.c https://pastebin.com/Jd4i1ecr

在 sorter.h 中

#define MAXTHREAD 255
extern pthread_mutex_t lock;
typedef
struct _dir_proc
{
     char* path;        //the path to the new found directory
     char* colName;     //related to the other work that must be done
} dir_proc;

在 sorter.c 中

#include <pthread.h>
#include <assert.h>
#include <dirent.h>
#include "sorter.h"

pthread_mutex_t lock;
int main(int argc, char* argv[])
{
      int err = 0;
      pthread_t threads[MAXTHREAD];
      DIR *dirPointer;
      char* searchedDirectory = ".";
      struct dirent *directEntry;
      dir_proc *dir_proc_args = malloc(sizeof(struct _dir_proc));
      assert(dir_proc_args != NULL);
      dir_proc_args->path = (char*) malloc(256 * (sizeof(char));
      assert(dir_proc_args->path != NULL);
      dir_proc_args->colName = (char*) malloc(256 * sizeof(char));
      assert(dir_proc_args->colName != NULL);
      pthread_mutex_init(&lock, NULL)

      //dir_proc_args->colName is saved here
      if(!(dirPointer = opendir(searchedDirectory)))
      {
           fprintf(stderr, "opening of directory has failed");
           exit(1);
      }

      while((directEntry = readdir(dirPointer)) != NULL)
      {
           //do stuff here to ensure it is a directory
           //ensure that the dir we are looking at is not current or parent dir
           //copy path of found directory to dir_proc_args->path
           err = pthread_create(&threads[count++], NULL, &CSVFinder, (void*)dir_proc_args);
           if(err != 0)
               printf("can't create thread);
      }
      int i;
      for(i=0; i < count; ++i)
      {
              pthread_join(threads[i], NULL);
      }
      pthread_mutex_destroy(&lock);
}

在 CSVFinder 函数中

#include <assert.h>
#include <pthread.h>
#include "sorter.h"
#include <dirent.h>

void *CSVFinder(void *args)
{
      pthread_mutex_lock(&lock);  //I have locked the entire function to see I can get it to work. this makes no sense to actually do
      DIR *dirPointer;
      struct dirent *directEntry;
      dir_proc *funcArgs = (struct _dir_proc*)args;
      char path[255];
      strncpy(path, funcArgs->path, sizeof(path));

      if(!(dirPointer = opendir(funcArgs->path)))
      {
              fprintf(stderr, "opening of directory has failed");
              exit(1);
      }
      while((directEntry = readdir(dirPointer)) != NULL)
      {
           if(directEntry->d_type == DT_DIR)     //if we are looking at a directory
           {
                  //make sure the dir we are looking at is not current or parent dir
                  snprintf(funcArgs->path, (sizeof(path) + sizeof(directEntry->d_name)), "%s/%s", path, directEntry->d_name);
                 //I would like to be able to do a recursive call here
                 //to search for more directories but one thing at a time
           }
       }
      closedir(dirPointer);
      pthread_mutex_unlock(&lock);
      return(NULL);
}

我希望我没有遗漏任何相关代码。我试图将代码保持在最低限度,同时不遗漏任何必要的内容。

【问题讨论】:

  • '因为我需要在查找新目录的每个实例上使用线程' - 不,不要那样做。它不会有效,(事实上,适得其反)。使用一个线程执行 I/O 绑定目录/文件扫描,如果需要对每个文件执行 CPU 密集型任务(例如压缩),则将文件规范(在一些合适的结构中)排队,以一个线程池。
  • 啊,但你没有把我带到这里。我必须这样做。我完全同意你所说的。在现实生活中我永远不会这样做,但这是任务,我必须这样做。这没有任何意义。
  • 好吧,分配 'dir_proc *dir_proc_args' 并加载它就可以了..除了你只做一次然后为每个线程使用相同的 dir_proc_args 实例。这不会有好的结局。 malloc 为每个线程分配一个单独的实例,否则“您发送给函数的参数将被覆盖”。
  • count 声明/初始化在哪里?您还缺少您的printfs 之一的结束"。发布您实际运行的代码是最有帮助的,如果可能,最好复制粘贴。
  • @MartinJames 这可能是问题的解决方案。我将 malloc 移动到循环内,它似乎正在工作。我将继续测试和扩展。实际上我最初是这样写的,但是代码给了我一个问题,我认为循环中的 malloc 给了我一个问题,所以我移动了它。我不能感谢你。我不得不承认我很困惑为什么这会解决问题。每次循环通过时,我都会更改结构的内容。

标签: c multithreading mutex locks


【解决方案1】:

我不清楚为什么要创建一个线程来简单地遍历目录结构。不过,我会指出一些我看到的问题。

一个小问题是你在 CSVFinder 函数中,你调用的是 readder,而不是 readdir。

但对我来说一个明显的问题是您没有在 main 或 CSVFinder() 函数中初始化 dirPointer。我希望看到这样的电话

dirPointer = opendir("/");

在 while 循环之前的 main() 函数中。

然后我希望看到 CSVFinder() 通过调用 opendir(path) 来初始化其 dirPointer,其中 path 是在主循环中找到的子目录的名称。

有关如何遍历目录结构的良好参考,请转到此处...

https://www.lemoda.net/c/recursive-directory/

【讨论】:

  • 再次,搜索目录树没有问题。不使用线程时,它可以完美运行。阅读器是我现在更正的类型。我还更新了代码以显示 dirPointer 的初始化位置。我试图将代码保持在最低限度,以免您阅读大量不相关的代码。对于疏忽,我深表歉意,并很乐意用您认为必要的任何其他信息更新原始帖子。
  • CSVFinder() 例程中的 dirPointer 怎么样?那个是用 opendir() 初始化的吗?
  • 我已按照以下方式得到指示“在找到目录时启动一个新线程来搜索该目录”。不是我的决定。
  • @demist。我能告诉你的最好的就是搜索目录的算法已经被证明是有效的。它已经工作了数百次(没有线程),每次都很完美。现在可能的情况是,不可能使用带有线程的算法,但没有线程它可以正常工作。
  • 它当然可以与线程一起使用。如果您在 CSVFinder() 中初始化 dirPointer,请告诉我?如果你不是,那显然是个问题。 CSVFinder 中的 dirPointer 是 main 中 dirPointer 的另一个实例。
猜你喜欢
  • 1970-01-01
  • 2013-01-31
  • 2012-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-23
  • 1970-01-01
相关资源
最近更新 更多