2009-07-21 34 views
28

Para procesos secundarios, las funciones wait() y waitpid() se pueden utilizar para suspender la ejecución del proceso actual hasta que un elemento secundario haya salido. Pero esta función no se puede usar para procesos que no sean secundarios.Cómo esperar la salida de procesos no secundarios

¿Hay alguna otra función que pueda esperar la salida de cualquier proceso?

Respuesta

25

Nada equivalente a wait(). La práctica habitual es sondear usando kill(pid, 0) y buscando el valor de retorno -1 y errno de ESRCH para indicar que el proceso se ha ido.

+2

¿Está bien tener ese ajetreo? – CsTamas

+1

Bueno, no quiere que esté demasiado ocupado; deberías 'usleep()' por un tiempo después de cada 'kill()' que no encuentra que el proceso se haya ido. Luego debe establecer un equilibrio entre cuán ocupada está su encuesta y cuánto tiempo está bien para que el proceso desaparezca antes de que se dé cuenta. – chaos

+0

Oh, 'usleep()' se volvió obsoleto cuando aparentemente no estaba mirando. Parece que ahora debes 'nanosleep()' en su lugar. – chaos

2

Ninguno Sé de. Además de la solución del caos, puede usar semáforos si puede cambiar el programa que desea esperar.

Las funciones de la biblioteca son sem_open(3), sem_init(3),sem_wait(3), ...

sem_wait(3) realiza una espera, por lo que no tiene que hacer la espera activa como en la solución de chaos'. Por supuesto, el uso de semáforos hace que sus programas sean más complejos y puede que no valga la pena.

+0

Estos semáforos son prácticamente inútiles, ya que persisten incluso si ningún proceso los tiene abiertos. Recuerdo haber llamado periódicamente a ipcrm para limpiar los restos de algún proceso bloqueado. –

4

También puede crear un socket o un FIFO y leer en ellos. El FIFO es especialmente simple: conecte la salida estándar de su hijo con el FIFO y lea. La lectura se bloqueará hasta que el niño salga (por cualquier razón) o hasta que emita algunos datos. Por lo tanto, necesitará un pequeño bucle para descartar los datos de texto no deseados.

Si tiene acceso a la fuente del niño, abra el FIFO para escribir cuando se inicia y luego simplemente olvídese de ello. El sistema operativo limpiará el descriptor de archivo abierto cuando el niño termine y su proceso de "padre" en espera se activará.

Ahora bien, este podría ser un proceso que no inició ni tuvo. En ese caso, puede reemplazar el ejecutable binario por un script que inicie el binario real pero también agregue monitoreo como se explicó anteriormente.

+2

Pero el proceso no es un niño ... – LtWorf

+0

No es un niño y, especialmente, podría no estar diseñado teniendo en cuenta este seguimiento y no podría modificar el código fuente. – Lothar

+0

@Lothar Creo que es bueno mostrar alguna solución fuera de lo obvio, especialmente porque la respuesta aceptada no es confiable. Además, cualquier proceso puede convertirse en un niño de alguna manera. Por ejemplo, puede reemplazar el binario con un script que supervisa el binario original y envía una señal cuando muere el ahora hijo. –

1

Quizás sea posible esperar a que desaparezca/proc/[pid] o/proc/[pid]/[algo]?

Hay encuesta() y otras funciones de espera de eventos de archivo, ¿quizás eso podría ayudar?

+0

Sí, es una buena idea. A menos que el mismo ID de proceso se reutilice tan rápido, pero probablemente esto ocurra raramente – CsTamas

+0

@CsTamas, existe una protección donde el número de identificadores de proceso (32768) es mucho mayor que el número de procesos que se pueden ejecutar. Entonces la probabilidad de que obtenga el mismo identificador de proceso es muy baja a menos que se quede dormido por un tiempo. –

3

Podría conectarse al proceso con ptrace(2). Desde el shell, strace -p PID >/dev/null 2>&1 parece funcionar. Esto evita la espera ocupada, aunque ralentizará el proceso trazado y no funcionará en todos los procesos (solo el suyo, que es un poco mejor que los procesos secundarios).

+1

El conocimiento nunca daña, pero para las conchas, recomiendo la forma "estándar", sondeando periódicamente; ver [pregunta 1058047] (http://stackoverflow.com/questions/1058047/wait-for-any-process-to-finish). Aunque puede ser un caso raro, pero strace puede hacer un ciclo ocupado. Ej. $ (Leer) &; strace -p $ !.Tenga en cuenta que (leer) y en sí mismo es inofensivo. –

12

En BSD y OS X, puede usar kqueue con EVFILT_PROC + NOTE_EXIT para hacer exactamente eso. No se requiere votación. Desafortunadamente no hay un equivalente de Linux.

+5

Lástima que no hayan portado kqueue en Linux. – Lothar

6

Hasta ahora he encontrado tres maneras de hacer esto en Linux:

  • Sondeo: se comprueba la existencia del proceso de vez en cuando, ya sea mediante el uso de kill o mediante pruebas de la existencia de /proc/$pid , como en la mayoría de las otras respuestas
  • utilizar la llamada ptrace sistema para asociar al proceso como un depurador para que recibir una notificación cuando sale, como en a3nm's answer
  • uso de la interfaz netlink para escuchar PROC_EVENT_EXIT mensajes - de esta manera la K ernel le dice a su programa cada vez que sale un proceso y usted simplemente espera la identificación correcta del proceso. Solo he visto esto descrito in one place on the internet.

Shameless plug: Estoy trabajando en un program (código abierto, por supuesto, GPLv2) que hace cualquiera de los tres.

Cuestiones relacionadas