2010-05-19 2 views
7

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

Я играл со следующим кодом, и выяснилось, что информация о статусе выхода действительна в течение как минимум нескольких секунд после того, как ребенок закончил, но я не знаю, как долго или как сообщить ОС, что я не будет вызывать 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; 
} 

ответ

10

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

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

+0

Действительно, второй вызов waitpid был неудачным. Я об этом не думал! Спасибо, что указали это. –

3

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

2

Да.

Из man page:

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