2012-01-23 16 views
7

He entendido que: 1) waitpid se utiliza para esperar la muerte de un niño y luego recoger el SIGCHLD y el estado de salida del niño, etc. 2) Cuando tenemos un manejador de señal para SIGCHLD, hacemos algunas cosas más relacionado con la limpieza del niño u otras cosas (hasta el programador) y luego haga un waitpid para que el niño no se vuelva zombie y luego regrese.¿Usando waitpid o sigaction?

Ahora, ¿necesitamos tener ambos 1 y 2 en nuestros programas cuando hacemos un fork/exec y el niño regresa? Si tenemos tanto, la SIGCHLD se obtiene en primer lugar, por lo que el manejador de la señal se llama primero y por tanto su waitpid se llama éxito y no el waitpid en el código del proceso padre de la siguiente manera:

my_signal_handler_for_sigchld 
{ 
do something 
tmp = waitpid(-1,NULL,0); 
print tmp (which is the correct value of the child pid) 
} 

int main() 
{ 
    sigaction(SIGCHLD, my_signal_handler_for_sigchld) 
    fork() 
    if (child) //do something, return 
    if parent // waitpid(child_pid, NULL,0); print value returned from this waitpid - it is -1 
} 

Apreciar si alguien me ayuda Entienda esto.

Respuesta

1

Necesita llamar a las llamadas de sistema de espera como waitpid o amigos -eg wait4 etc.- de lo contrario podría tener zombie processes.

Puede manejar SIGCHLD para recibir notificaciones de que algún niño ha finalizado (o detenido, etc.) pero tendrá que esperarlo más tarde.

Los controladores de señal están limitados a llamar a un pequeño conjunto de funciones de seguridad de señal asíncrona (consulte signal(7) para obtener más información). Un buen consejo es establecer una bandera volatile sig_atomic_t en el interior, y probarla en lugares posteriores y más seguros.

18

Realmente no necesita manejar SIGCHLD si su intención es ejecutar un proceso secundario, hacer algunas cosas, luego esperar a que termine. En ese caso, simplemente llame al waitpid cuando esté listo para sincronizar. Lo único que es útil para SIGCHLD es la notificación asíncrona de terminación de hijos, por ejemplo, si tiene una aplicación interactiva (o demonio de larga ejecución) que está generando varios hijos y necesita saber cuándo terminan. Sin embargo, SIGCHLD es realmente malo/feo para este propósito también, ya que si está utilizando un código de biblioteca que crea procesos hijos, puede detectar los eventos para los hijos de la biblioteca que terminan e interferir con el manejo de los mismos. Los manejadores de señal son intrínsecamente globales del proceso y se ocupan del estado global, que generalmente es A Bad Thing (tm).

Aquí hay dos enfoques mejores para cuando se tiene procesos hijo que será por concluidas de forma asíncrona:

Enfoque 1 (select/poll basada en eventos): Asegúrate de que tienes una tubería a/de cada proceso hijo se crea . Puede ser stdin/stdout/stderr o solo un dummy extra fd. Cuando finalice el proceso secundario, su extremo de la tubería se cerrará, y su bucle de evento principal detectará la actividad en ese descriptor de archivo. Por el hecho de que se cerró, reconoces que el proceso del niño murió y llamas al waitpid para cosechar al zombi.

Método 2 (basado en subprocesos): Para cada proceso secundario que cree, también cree un subproceso que llame inmediatamente al waitpid en el pid del proceso secundario. Cuando waitpid regresa exitosamente, use sus primitivas de sincronización de hilo favoritas para que el resto del programa sepa que el niño terminó, o simplemente cuide todo lo que necesita hacer en este hilo de mesero antes de que termine.

Ambos enfoques son modulares y compatibles con las bibliotecas (evitan interferir con otras partes de su código o código de biblioteca que podrían estar haciendo uso de procesos secundarios).

+0

Hola, gracias por tu respuesta.Pero lo que realmente estaba buscando es: cuando tengo sig_handler y waitpid en el proceso padre, sig_handler se llama becaues de sigchld y luego el 2nd waitpid como se muestra arriba en mi pregunta devuelve -1. Entonces, ¿puedo eliminar el 2do waitpid que estoy teniendo? – Vin

+0

Sí, solo puede esperar satisfactoriamente un proceso hijo determinado una vez. En realidad, es un error esperar nuevamente ya que el pid es "liberado" en la primera espera y puede haber sido reutilizado para un nuevo proceso secundario (si es que ha creado otro). –

+0

@R .. ¿Podríamos aclarar el 'Cuando el proceso secundario termina, su extremo de la tubería se cerrará? Un poco? Para ser realmente preciso, ¿no sería 'Cuando el proceso secundario cierra su FD que está conectado al extremo de la tubería, y no hay otros procesos que tengan FD conectados a ese extremo de la tubería, entonces el otro extremo de la tubería será señalado como cerrado (recibe EOF) '? Creo que eso explicaría con mayor precisión lo que sucede, y también el caso especial importante de lo que sucede si se abren más de 2 procesos con FDs en una tubería. – nh2