c中的递归多进程程序

时间:2014-10-22 14:31:22

标签: c recursion multiprocess

我正在开发一个相当简单的程序,它应该打印出一个给定路径的文件树。该程序只使用直接递归,但当我修改它以分叉一个新的子进程迭代每个新目录时,我开始得到一些奇怪的输出。似乎允许进程向后移动到其父目录。

我一直在名为test的小样本文件夹上测试它。测试包含2个文件(testFile1和testFile2)和一个文件夹(testSub)。文件夹testSub只包含2个文件(testSubFile1和testSubFile2)。据我所知,应该遍历testSub文件夹的子进程正在执行该操作,然后将目录移动到测试文件夹并迭代它。

#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;
}

代码包含了一些注释掉的printf语句,我用它来尝试调试正在发生的事情。老实说,我只是不知所措,我不知道还有谁问。我真的很想知道我做错了什么,所以如果有人能指出我正确的方向,我会非常感激。

2 个答案:

答案 0 :(得分:2)

可能发生的事情是readdir()按照文件系统出来的顺序读取文件,这与ls显示事物的方式无关。 readdir()是原始/未排序的输出,而默认情况下ls按名称排序所有内容。

e.g。你的磁盘文件结构可能是这样的:

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

由于readdir按照存储在目录列表中的顺序返回所有内容,因此您将.,然后..testFiletestSub,递归到test ,然后返回主testFile2目录并继续exit()

请注意,您没有检查文件类型。您将尝试对实际文件执行opendir()调用,这将失败,并导致该特定进程stat。您应该检查由{{1}}返回的文件类型,并且只在它实际上是目录时执行递归调用。

答案 1 :(得分:0)

我明白了!

这个问题是因为一个孩子在递归语句中被分叉了x个级别,虽然我知道每个孩子与其父级相同,但我并不认为这个孩子在自己的递归堆中会有x级深度。

在孩子返回之前,它必须循​​环退出所有递归调用。我通过在exit(EXIT_SUCCESS);语句之后添加语句closedir(dir);解决了这个问题,因此它不会返回所有级别的递归,只要它完成自己的目录就会退出。

感谢大家的帮助!