【问题标题】:Recursive function to traverse directories using fork() running too many times使用 fork() 遍历目录的递归函数运行次数过多
【发布时间】:2019-03-26 01:41:47
【问题描述】:

我试图通过遍历 C 中的目录来更好地理解 fork 进程的概念。

我的功能没有按预期工作:我的一些目录和文件被多次访问。

我应该从当前工作目录开始并列出所有文件/文件夹。每次找到子目录时,我都应该调用 fork() 并执行相同的操作,直到我用尽了每个文件/目录。我不需要按任何特定顺序访问这些项目,但我确实需要对每个项目都进行一次访问。

我让程序在没有使用 fork() 的情况下递归地工作。但我不能用 fork() 完全正确。这是功能。它只是通过字符串“.”,在当前工作目录启动它。

int traverse(char* directory)
{
    struct dirent *currentDir;  
    DIR *traverser = opendir(directory);

    if (traverser == NULL)
    {
        printf("Error: Could not open directory.\n");
        return 0;
    }

    while ((currentDir = readdir(traverser)) != NULL)
    {       
        if (currentDir->d_type == DT_DIR && strcmp(currentDir->d_name, ".") != 0 && strcmp(currentDir->d_name, "..") != 0)
        {
            int PID = fork();
            forkCount++;

            char pathBuffer[1024];

            if (PID == 0)
            {
                snprintf(pathBuffer, sizeof(pathBuffer), "%s/%s", directory, currentDir->d_name);
                traverse(pathBuffer);
            }
            else
            {
                listOfPIDS[forkCount] = PID;
                int status = 0;
                wait(&status);
            }
        }
        else if (strcmp(currentDir->d_name, ".") != 0 && strcmp(currentDir->d_name, "..") != 0)
        {
            printf("%s\n", currentDir->d_name);
        }
    }

    closedir(traverser);
    return 0;
}

【问题讨论】:

  • if (PID == 0) 之后,孩子将调用traverse,当traverse 返回时,孩子将继续while 循环。在等待孩子之后,父母还将继续while 循环。所以我希望第一个子目录将被访问一次,第二个子目录将被访问两次,依此类推。
  • 谢谢!您的观察帮助我找到了解决方案。

标签: c recursion directory


【解决方案1】:

在考虑了其他用户的评论并尝试了更多之后,我想出了这个解决方案。通过在子进程递归调用函数后中断while() 循环,不会重新访问相同的文件夹/文件。正如其他用户在他们的评论中指出的那样,当父级调用 fork 并开始等待时,子级开始并再次递归调用该函数。一旦孩子的递归调用完成,它就会返回到目录中完全相同的位置并开始列出所有文件。完成后,父级完成等待,并返回完全相同的位置并开始列出文件。所以父母和孩子都回到了目录和列出文件的同一个地方。只需在孩子的递归调用完成执行后添加exit(0);即可解决问题。另外,我将pathBuffer[]forkCount++ 移到子进程部分,因为父进程不需要担心。

代码如下:

int traverse(char* directory)
{
    struct dirent *currentDir;  
    DIR *traverser = opendir(directory);

    if (traverser == NULL)
    {
        printf("Error: Could not open directory.\n");
        return 0;
    }

    while ((currentDir = readdir(traverser)) != NULL)
    {       
        if (currentDir->d_type == DT_DIR && strcmp(currentDir->d_name, ".") != 0 && strcmp(currentDir->d_name, "..") != 0)
        {
            int PID = fork();

            if (PID == 0)
            {
                forkCount++;        
                char pathBuffer[1024];
                snprintf(pathBuffer, sizeof(pathBuffer), "%s/%s", directory, currentDir->d_name);
                traverse(pathBuffer);
                exit(0);
            }
            else
            {
                listOfPIDS[forkCount] = PID;
                int status = 0;
                wait(&status); //wait at end
            }
        }
        else if (strcmp(currentDir->d_name, ".") != 0 && strcmp(currentDir->d_name, "..") != 0)
        {
            printf("%s: Proc'd by %d\n", currentDir->d_name, getpid());
        }
    }

    closedir(traverser);
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-07
    • 1970-01-01
    • 2010-12-08
    • 2019-06-24
    • 1970-01-01
    • 2016-06-04
    • 2013-06-01
    • 1970-01-01
    相关资源
    最近更新 更多