Рекурсивная функция для обхода каталогов с использованием fork (), выполняемой слишком много раз - PullRequest
0 голосов
/ 22 октября 2018

Я пытаюсь лучше понять концепцию разветвления процесса путем обхода каталога в C.

Моя функция не работает так, как я ожидаю: некоторые из моих каталогов и файлов работаютпосетил несколько раз.

Я должен начать с текущего рабочего каталога и перечислить все файлы / папки.Каждый раз, когда подкаталог найден, я должен вызывать 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;
}

1 Ответ

0 голосов
/ 23 октября 2018

После того, как я принял к сведению комментарий другого пользователя и поиграл еще немного, я придумал это решение.Прерывая цикл 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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...