Выдает ли waitpid действительную информацию о состоянии для дочернего процесса, который уже завершился? - PullRequest
7 голосов
/ 19 мая 2010

Если я fork дочерний процесс и дочерний процесс завершается до того, как родительский вызов вызывает waitpid, то остается ли действительной информация о состоянии выхода, установленная waitpid? Если да, то когда он становится недействительным; то есть, как я могу гарантировать, что я могу вызвать waitpid для дочернего pid и продолжать получать действительную информацию о состоянии выхода через произвольное время, и как я могу "очистить" (скажите ОС, что я больше не заинтересован в информации о состоянии выхода для завершенного дочернего процесса)?

Я играл со следующим кодом, и похоже, что информация о состоянии выхода действительна в течение, по крайней мере, нескольких секунд после того, как ребенок заканчивает игру, но я не знаю, как долго или как сообщить ОС, что я выиграл больше не буду звонить waitpid:

#include <assert.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main()
{
    pid_t pid = fork();

    if (pid < 0) {
        fprintf(stderr, "Failed to fork\n");
        return EXIT_FAILURE;
    }
    else if (pid == 0) { // code for child process
        _exit(17);
    }
    else { // code for parent
        sleep(3);

        int status;
        waitpid(pid, &status, 0);
        waitpid(pid, &status, 0); // call `waitpid` again just to see if the first call had an effect
        assert(WIFEXITED(status));
        assert(WEXITSTATUS(status) == 17);
    }

    return EXIT_SUCCESS;
}

Ответы [ 3 ]

12 голосов
/ 19 мая 2010

Да, waitpid будет работать после выхода ребенка. Операционная система будет хранить запись дочернего процесса в таблице процессов (включая состояние выхода) примерно до тех пор, пока родительский вызов не вызовет waitpid (или другую функцию wait -семейства), или до тех пор, пока родительский процесс не завершится (в этот момент статус собирается init процесс). Вот что такое процесс «зомби»: процесс, который завершился, все еще находится в таблице процессов именно для этой цели.

Запись процесса в таблице должна исчезнуть после первого вызова waitpid. Я подозреваю, что причина того, что в вашем примере вы, кажется, можете вызвать waitpid дважды, заключается просто в том, что waitpid не изменит аргумент status, если pid больше не существует. Таким образом, первый вызов должен работать и заполнять status, а второй вызов должен возвращать код ошибки и не изменять status. В этом можно убедиться, проверив возвращаемые значения вызовов waitpid и / или используя две разные переменные status.

3 голосов
/ 19 мая 2010

ОС сохраняет завершенный процесс в состоянии zombie до тех пор, пока его родитель (не может быть init, если исходный родительский процесс завершился ранее) не соберет этот статус завершения с помощью системного вызова wait(2).Таким образом, ответ - статус выхода процесса не становится недействительным .

2 голосов
/ 19 мая 2010

Да.

Со страницы руководства :

Ребенок, который завершается, но его не ждали, становится "зомби".Ядро поддерживает минимальный набор информации о процессе зомби (PID, статус завершения, информация об использовании ресурсов), чтобы позволить родителю позднее выполнить ожидание для получения информации о дочернем элементе.

...