Más contenido relacionado
La actualidad más candente (18)
Similar a sistemas operativos (20)
Más de Juan Timoteo Cori (20)
sistemas operativos
- 1. Sistemas Operativos
Práctica 5
Al igual que el núcleo del sistema trabaja mediante interrupciones, para procesos a nivel de núcleo, el sistema nos
ofrece un mecanismo análogo para trabajar con los procesos a nivel de usuario: las señales. Existen multitud de señales
en el sistema. Podemos encontrarlas definidas en el archivo
/usr/include/asm/signal.h
Con ellas trabajan todos los procesos, echadles un vistazo.
La forma de capturarlas es mediante signal (man signal para más detalles). La llamada al sistema signal tiene dos
parámetros uno de ellos es la señal que esperamos recibir, y el otro el puntero a la rutina de servicio que vamos a
ejecutar en el momento que la recibamos. Podemos ayudarnos, a veces, de pause() que suspende la ejecución del
proceso hasta que recibe una señal.
por ejemplo. El siguiente código programa al manejador de reloj para que nos avise dentro de 5 segundos y espera a
recibir las señal SIGALRM. Una vez recibida, se salta a la rutina de servicio alarma que imprime un mensaje y
continua la ejecución normal del proceso.
#include <signal.h>
void alarma()
{
printf("acabo de recibir un SIGALRMn");
}
main()
{
signal(SIGALRM,alarma);
printf("acabo de programar la captura de un SIGALRMn");
alarm(3);
printf("ahora he programado la alarma para que venga en 3 segundosn");
pause();
printf("ahora continúo con la ejecución normaln");
}
El sistema tiene por defecto un par de manejadores para el tratamiento de todas y cada una de las señales: SIG_DFL y
SIG_IGN. El primero de ellos, realiza un exit con el número de señal que recibe, mientras que el segundo de ellos,
ignora la señal que llega.
En el ejemplo anterior, si comento la línea del signal, compilo y ejecuto el programa, comprobaré que no se imprime la
última línea debido a que por defecto el sistema posee un manejador SIG_DFL que hace exit con el número de señal
recibida.
En el estandar POXIS, hay que tener en cuenta que una vez recibida la señal, se desprograma el manejador, de manera
que si recibiésemos un segundo SIGALRM me mataría. En LINUX no ocurre así. El siguiente ejemplo lo ilustra.
#include <signal.h>
void alarma() {
printf("acabo de recibir un SIGALRMn");
}
main(){
signal(SIGALRM,alarma);
- 2. printf("acabo de programar la captura de un SIGALRMn");
alarm(3);
printf("ahora he programado la alarma para que venga en 3 segundosn");
pause();
printf("vuelvo a programar la alarman");
alarm(3);
pause();
printf("En POXIS esta línea nunca se ejecutaría porque me ha matado el SIGALRMn");
}
Una señal muy utilizada es SIG_CHILD que es enviada por todo proceso hijo a su
Padre en el mismo instante que realiza exit. De ésta manera, el padre sabe que su hijo ha pedido terminar. Ejemplo. El
siguiente programa, una vez convertido en proceso, tiene un hijo que realiza exit(5). El padre captura el 5.
#include <signal.h>
int status;
void finhijo(){
wait(&status);
}
main(){
signal(SIGCHLD,finhijo);
if (fork()==0) {sleep(3); exit(5);}
pause();
printf("mi hijo ha muerto con estado %dn",status/256);
printf(“ahora continúo con la ejecuciónn”);
}
Entre procesos, es posible enviarse señales aunque, para ello, es necesario conocer el PID del proceso al que se le envía
la señal. Como podeis ver en /usr/include/asm/signal.h el sistema define dos señales para los procesos de usuario:
SIGUSR1 y SIGUSR2.
Ejercicio: realizar un programa que cree un proceso y que el padre envíe un SIGUSR1 a su hijo. Cuando este lo reciba
que imprima en pantalla que ha capturado una señal, el printf debe estar incrustado en el manejador de esta señal.
Hecho esto, el padre realizará un pause mientras que el hijo terminará su ejecución con un exit (El valor del exit será
pasado como parámetro a main). Al realizar esto, el padre capturará su estado y lo imprimirá en pantalla. Ahora, de
nuevo el padre tendrá un hijo que ejecutará la orden “ls –lR” del raíz. De nuevo se pide que se capture el estado de
finalización y se imprima en pantalla.