CUESTIÓN
El programa que he hecho se para a veces.
O en mi casa se para, pero en clase, no.
O en clase sí, pero en casa, no.
Normalmente da una vuelta pero ya no da más.
SOLUCIÓN
El problema suele provenir de un mal uso de pause. Supongamos
que tenemos dos procesos, P0 y P1. P1, al arrancar, debe imprimir "Hola".
Cuando P0 le mande SIGUSR1, P1 debe imprimir "Adiós".
Mientras no se lo mande, P1 se debe quedar
parado sin consumir CPU. Una solución que se os puede ocurrir
es:
****** ******
* P0 * * P1 *
****** ******
/* Ya tenemos registrada SIGUSR1 para
no hacer nada. */
/* Espera un poco */ printf("Hola.\n"); fflush(stdout);
kill(pid_P1, SIGUSR1); pause(); /* Nos paramos sin consumir CPU */
... printf("Adiós.\n"); fflush(stdout);
Esta solución está mal. Si P1 es lo suficientemente rápido en
ejecutarse para llegar al pause antes de que le manden
la señal, todo irá bien. Sin embargo, si P0 es muy rápido y envía la
señal de modo que P1 la recibe antes de llegar al pause,
P1 saltará a la manejadora antes. Cuando llegue al pause,
se quedará bloqueado porque P0, que no sabe nada, no mandará de nuevo
la señal.
Lo más sencillo para evitar este tipo de problemas es que sigáis una
modo de programación orientada al suceso pura para hacer la
práctica. El esquema que puede seguir vuestra función main
podría ser el siguiente:
- Obtención de argumentos, iniciación de variables, registro
de señales, etc.
- Rutina de creación de hijos. A la entrada de este zona del
programa sólo está el padre. A la salida, están todos los
procesos que forman el anillo.
- Nos las apañamos para que todos los procesos pasen por aquí.
Si soy el hijo más pequeño, mando la señal SIGUSR1 al padre
de todos.
for (;;) pause();
De este modo, todos los procesos acabarán en un bucle infinito de
pauses. Sólo reaccionarán a las señales que reciban.
Si reciben SIGUSR1, saltarán a la manejadora, donde transmitirán
la señal a su hijo, si procede. Si la señal recibida es SIGCHLD,
significa que su hijo ha muerto, hay que tomar su código de retorno
y transformarlo para, una vez muertos, devolvérselo a nuestro
padre.
NOTA: Este LPE es una orientación. No significa que debáis por fuerza
seguir estas indicaciones.
© 2003 Guillermo González Talaván.