简体   繁体   English

C语言中的递归多进程程序

[英]Recursive multi-process program in c

I am working on a fairly simple program that should print out a file tree given a path. 我正在开发一个相当简单的程序,该程序应打印出给定路径的文件树。 The program worked with just straight recursion but when I modified it to fork a new child process to iterate over each new directory I started getting some weird output. 该程序仅使用直接递归工作,但是当我对其进行修改以派生一个新的子进程来遍历每个新目录时,我开始得到一些奇怪的输出。 It appears that processes are being allowed to move backwards to their parent directory. 似乎允许进程向后移动到其父目录。

I have been testing it on a small sample folder called test. 我一直在一个名为test的小样本文件夹中对其进行测试。 Test contains 2 files (testFile1 and testFile2) and a folder (testSub). 测试包含2个文件(testFile1和testFile2)和一个文件夹(testSub)。 The folder testSub only contains 2 files (testSubFile1 and testSubFile2). 文件夹testSub仅包含2个文件(testSubFile1和testSubFile2)。 As far as I can tell, the child process that is supposed to iterate through the testSub folder is doing that and then moving up a directory to the test folder and iterating through that. 据我所知,应该遍历testSub文件夹的子进程正在这样做,然后将目录上移至test文件夹并进行遍历。

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <unistd.h>

int recFork(char *path){
    /*int key = rand() % 113;
    printf("--------\n--------\n");
    printf("New function\n");
    printf("Key: %d\n", key);
    printf("path: %s\npid: %d\n", path, getpid());
    printf("--------\n--------\n");*/
    int status;
    pid_t pID = 1;
    char name[1024];
    struct stat statbuf;
    if(stat(path, &statbuf) == -1)
        return -1;

    /* if the item is a file */
    if(S_ISREG(statbuf.st_mode)){
        printf("pID: %d   ", getpid());
        printf("%s\t%8ld\n", path, statbuf.st_size);
    }

    /* if the item is a directory */
    else if((statbuf.st_mode & S_IFMT) == S_IFDIR){
        pID = fork();

       if(pID > 0){    //parent
           //printf("Forked child with pID: %d\n", pID);
           waitpid(pID, &status, WUNTRACED);
           //printf("Killed: %d\n", pID);
       }
       else if(pID == 0){   //child
           //printf("Child: %d\n", getpid());
           DIR *dir;
           struct dirent *dp = NULL;
           if ((dir = opendir(path)) == NULL){
               printf("Cannot open %s\n", path);
               exit(EXIT_FAILURE);
           }
           else{
               printf("DIR: %s/\n", path);
               while((dp = readdir(dir)) != NULL){
                   //printf("pID: %d key: %d dp = %s\n", getpid(), key, dp->d_name);
                   if(strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
                       continue;
                   sprintf(name, "%s/%s", path, dp->d_name);
                   //printf("Process: %d  Key: %d\n", getpid(), key);
                   //printf("I was passed: %s\n", path);
                   //printf("Calling recFork(%s)\n\n", name);
                   recFork(name);
               }
               closedir(dir);
           }
       }
       else{   //failed to fork
           printf("Failed to fork\n");
           exit(EXIT_FAILURE);
       }
    }

    //printf("Returning from : %d with key: %d\n", getpid(), key);

    return 0;
}

The code includes quite a few commented out printf statements that I was using to try and debug what was going on. 该代码包含了很多注释掉的printf语句,这些语句是我用来尝试调试发生的事情的。 Honestly I'm just at a loss and I don't know who else to ask. 老实说,我很茫然,我不知道还有谁要问。 I really would like to learn what I am doing wrong so if someone can point me in the right direction that would be much appreciated. 我真的很想了解我在做错什么,因此,如果有人可以向我指出正确的方向,那将不胜感激。

What's probably happening is readdir() reading files in the order that they come out of the filesystem, which has no relation to how ls displays things. 可能发生的情况是readdir()文件从文件系统中读取的顺序读取文件,这与ls显示内容的方式无关。 readdir() is raw/unsorted output, while ls by default sorts everything by name. readdir()是原始/未排序的输出,而ls默认情况下按名称对所有内容进行排序。

eg your on-disk file structure may be something like this: 例如,您的磁盘上文件结构可能是这样的:

./test/.
./test/..
./test/testFile1
./test/testSub/.
./test/testSub/..
./test/testFile2

Since readdir is returning everything in the order it's stored in the directory listing, you'll get . 由于readdir按存储在目录列表中的顺序返回所有内容,因此您将获得. , then .. , work on testFile , recursive into testSub , then go back UP to the main test dir and work on testFile2 . ,然后.. ,处理testFile ,递归到testSub ,然后返回到主test目录并处理testFile2

And note that you're not checking for type-of-file. 并请注意,您并未检查文件类型。 You'll be attempting opendir() calls on the actual files, which will fail, and cause that particular process to exit() . 您将尝试在实际文件上进行opendir()调用,这将失败,并导致特定进程exit() You should be checking filetypes as returned by stat and only doing the recursive calls when it's actually a directory. 您应该检查stat返回的文件类型,并且仅在实际上是目录时才进行递归调用。

I figured it out! 我想到了!

The issue was because a child was forked x number of levels deep in recursive statements and though I know each child is identical to its parent I didn't think that the child would be x levels deep in its own recursive pile. 问题是因为一个孩子在递归语句中被分叉了x个层次,尽管我知道每个孩子都和它的父母相同,但我不认为那个孩子在自己的递归堆中会被x个层次。

Before a child would return it had to cycle back out of all of the recursive calls. 在孩子返回之前,它必须循​​环退出所有递归调用。 I solved the issue by adding the statement exit(EXIT_SUCCESS); 我通过添加语句exit(EXIT_SUCCESS);解决了该问题exit(EXIT_SUCCESS); right after the closedir(dir); 就在closedir(dir); statement so instead of returning through all of the levels of recursion it would just exit once it finished its own directory. 语句,所以它不会返回所有递归级别,而是会在完成自己的目录后立即退出。

Thanks everyone for your help along the way! 感谢大家在此过程中提供的帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM