CUESTIÓN
He seguido los consejos del LPE anterior. Sin embargo,
ahora me ocurre una situación un tanto extraña. ¡Hay
una variable que no funciona! El programa en esquema
es como sigue:
[[Código de iniciación, registro de SIGUSR1, etc.]]
mi_hijo=fork();
...
if (mi_hijo==0) /* Si soy el hijo menor */
{kill(padre_de_todos, SIGUSR1);
}
for (;;) pause();
[...]
void manejadora(int seNal)
{
printf("Soy %d y voy a mandar la señal a %d.\n",
getpid(),mi_hijo); fflush(stdout);
/* kill(mi_hijo,SIGUSR1); */
}
El hijo manda bien la señal al padre de todos porque
se imprime el mensaje de la manejadora del padre,
pero he tenido que comentar el kill
porque mi_hijo
vale 0. Su valor tiene
que ser el pid del hijo del padre (lo que
devolvió fork
) pero vale 0. Es como
si la variable global no funcionara. Además, en
mi casa sí que funciona. Me estoy volviendo loco.
SOLUCIÓN
Si funciona en casa y en el servidor de la facultad no, el diagnóstico
es claro: el programa está mal hecho.
El error no sale a la luz en Linux por la manera en que reparte la
CPU. En una instrucción como mi_hijo=fork();
, una vez
ejecutada fork()
, tenemos dos procesos, el padre y
el hijo. Para el hijo, fork()
devuelve 0. Para el padre,
fork()
devuelve el pid del hijo. Y ¡ojo!, que
he dicho que fork()
devuelve un valor. No he
dicho cuándo el valor devuelto por fork()
se va a almacenar
en la variable. Justo en el momento en que fork se ha acabado
de ejecutar, como nuestros ordenadores sólo tienen una CPU, el sistema
operativo debe decidir quién prosigue su ejecución, el padre o el hijo.
Ahí radica la diferencia entre Linux y el servidor de clase. Como no
está especificado, Linux cede la CPU al padre primero. El servidor
da la CPU al hijo en primer lugar. Veamos lo que ocurre en el servidor
de clase que es el que hace aparecer el error:
- Justo después del
fork
, tenemos el padre y el
hijo.
- En el servidor de clase, la CPU la toma el hijo. Manda la
señal SIGUSR1 al padre.
- El padre se encuentra parado justo antes de almacenar el
valor devuelto por
fork()
en la variable
mi_hijo
. Antes de poder hacerlo, el padre
salta a la manejadora y, claro está que la variable
contiene un cero.
La solución a este problema puede pasar por evitar que el padre
pueda saltar a la manejadora antes de haber almacenado el valor
de su variable. Esto se logra mediante el bloqueo de señales.
Si un proceso bloquea una señal y esta señal se produce,
el proceso no salta a la manejadora hasta que la señal sea
desbloqueada. Para poder bloquear y desbloquear señales,
podéis usar la llamada al sistema sigprocmask
.
© 2003 Guillermo González Talaván.