Practica No 3
Practica No 3
Practica No 3
Sistemas Operativos
Practica No 3
Seales
Contenido
Introduccin
Envo de una seal a otros procesos
Tratamiento de una seal
SIGALARM para crear temporizadores en nuestros programas
Ejemplo del uso de Seales entre procesos padre e hijo
Introduccin
En muchas situaciones los programas deben de estar preparados para tratar situaciones inesperadas o impredecibles,
como:
error en operacin en punto flotante,
aviso de un reloj de alarma,
la muerte de un proceso hijo,
solicitud de terminacin por parte del usuario (Control-C),
solicitud de suspensin por parte del usuario (Control-Z),
etc.
Cuando una de estas situaciones se produce, el kernel enva una seal al proceso correspondiente. Adems, cualquier
proceso puede enviar una seal a otro proceso, si tiene permiso. En System V hay definidas 19 seales, mientras que
BSD define 11 seales ms. Cuando un proceso recibe una seal puede tratarla de tres formas diferentes:
kill()
int kill ( int pid,int sig ) ;
- kill() enva la seal con valor sig al proceso cuyo PID es pid.
- La seal se enva de forma satisfactoria si el proceso que enva y el que recibe son del mismo usuario, o bien si el
proceso que enva es del superusuario.
- kill() funciona de forma diferente dependiendo del valor de pid:
UNAN-Leon
Sistemas Operativos
Si pid > 0 la seal se enva al proceso cuyo PID es pid.
Si pid = 0 la seal se enva a todos los procesos que pertenecen al mismo grupo del proceso
Si pid = -1 la seal se enva a todos procesos cuyo UID real es igual al UID efectivo del proceso que la enva. Si el
proceso que la enva tiene UID efectivo de superusuario, la seal es enviada a todos los procesos, excepto al proceso 0
(swapper) y 1 (init).
Si pid < -1 la seal es enviada a todos los procesos cuyo ID de grupo coincide con el valor absoluto de pid.
Para mostrar las seales que nos proporciona nuestro ncleo y su identificativo numrico asociado, usaremos
el siguiente comando:
~$ kill -l
1)
5)
9)
13)
18)
22)
26)
30)
34)
38)
42)
46)
50)
54)
58)
62)
SIGHUP
SIGTRAP
SIGKILL
SIGPIPE
SIGCONT
SIGTTOU
SIGVTALRM
SIGPWR
SIGRTMIN+2
SIGRTMIN+6
SIGRTMIN+10
SIGRTMIN+14
SIGRTMAX-13
SIGRTMAX-9
SIGRTMAX-5
SIGRTMAX-1
2)
6)
10)
14)
19)
23)
27)
31)
35)
39)
43)
47)
51)
55)
59)
63)
SIGINT
SIGABRT
SIGUSR1
SIGALRM
SIGSTOP
SIGURG
SIGPROF
SIGSYS
SIGRTMIN+3
SIGRTMIN+7
SIGRTMIN+11
SIGRTMIN+15
SIGRTMAX-12
SIGRTMAX-8
SIGRTMAX-4
SIGRTMAX
3)
7)
11)
15)
20)
24)
28)
32)
36)
40)
44)
48)
52)
56)
60)
SIGQUIT
SIGBUS
SIGSEGV
SIGTERM
SIGTSTP
SIGXCPU
SIGWINCH
SIGRTMIN
SIGRTMIN+4
SIGRTMIN+8
SIGRTMIN+12
SIGRTMAX-15
SIGRTMAX-11
SIGRTMAX-7
SIGRTMAX-3
4)
8)
12)
17)
21)
25)
29)
33)
37)
41)
45)
49)
53)
57)
61)
SIGILL
SIGFPE
SIGUSR2
SIGCHLD
SIGTTIN
SIGXFSZ
SIGIO
SIGRTMIN+1
SIGRTMIN+5
SIGRTMIN+9
SIGRTMIN+13
SIGRTMAX-14
SIGRTMAX-10
SIGRTMAX-6
SIGRTMAX-2
UNAN-Leon
Sistemas Operativos
printf(HIJO. PID = %d\n,getpid());
sleep(1);
}
}
sleep(10);
printf( PADRE. Terminacion del Proceso %d \n, pid);
kill (pid, SIGTERM);
exit(0);
}
Ignorar la seal.
Invocar a una rutina de tratamiento por defecto. Esta rutina la posee el kernel.
Invocar a una rutina creada por el usuario para tratar la seal.
#include <signal.h>
void (*signal (int sig, void (*accin) ())) ();
- signal() permite a un proceso especificar la accin a tomar cuando reciba una seal en particular.
- sig especifica el nmero de la seal a tratar.
- accin puede tomar:
SIG_DFL: indica que se use el manejador por defecto del kernel.
SIG_IGN: indica que la seal se debe ignorar.
Cuando queremos que un proceso espere a que le llegue una seal, usaremos la funcin pause(). Esta funcin
provoca que el proceso (o thread) en cuestin duerma hasta que le llegue una seal. Para capturar esa seal, el
proceso deber haber establecido un tratamiento de la misma con la funcin signal(). La funcin pause() no recibe
ningn parmetro y retorna 1 cuando la llamada a la funcin que captura la seal ha terminado.
#include <unistd.h>
int pause(void);
UNAN-Leon
Sistemas Operativos
UNAN-Leon
Sistemas Operativos
Ejemplo (Captura la seal cuyo Id asociado esta entre 1 y 64 ):
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void trapper(int);
main()
{
int i;
for(i=1;i<=64;i++)
signal(i, trapper);
printf("Proceso \n");
pause();
printf("Continuando...\n");
return 0;
}
void trapper(int sig)
{
signal(sig, trapper);
printf("Recibida la seal: %d\n", sig);
}
Explicacin del programa:
Inicialmente declaramos una funcin que va a recibir un entero como parmetro y se encargar de capturar una
seal (trapper() ). Seguidamente capturamos todas las seales de 1 a 64 haciendo 64 llamadas a signal(), pasando como
primer parmetro el nmero de la seal (i) y como segundo parmetro la funcin que se har cargo de dicha seal
(trapper). Seguidamente el programa espera a que le llegue una seal con la funcin pause(). El programa esperar
indefinidamente la llegada de esa seal, y cuando le enviemos una (por ejemplo, pulsando Control+C), la funcin
encargada de gestionarla (trapper() ) ser invocada. Lo primero que hace trapper() es volver a enlazar la seal en
cuestin a la funcin encargada de gestionarla, es decir, ella misma, y luego saca por la salida estndar la seal
recibida. Al terminal la ejecucin de trapper(), se vuelve al punto donde estbamos ( pause() ) y se continua:
UNAN-Leon
Sistemas Operativos
Ejemplo de su utilizacin:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void trapper(int);
main()
{
()
int i;
signal(14, trapper);
printf("Identificativo de proceso: %d\n", getpid() );
alarm(5);
pause();
alarm(3);
pause();
for(;;)
{
alarm(1);
pause();
}
return 0;
}
void trapper(int sig)
{
signal(sig, trapper);
printf("RIIIIIIIIING!\n");
}
Explicacin del programa:
Este programa es bastante similar al que hemos diseado antes para capturar seales, slo que ahora en lugar
de capturarlas todas, capturar nicamente la 14, SIGALARM. Cuando reciba una seal SIGALARM, sacar
RIIIIIIIIING por pantalla. El cuerpo del programa indica que se fijar una alarma de 5 segundos y luego se esperar
hasta recibir una seal, luego la alarma se fijar a los 3 segundos y se volver a esperar, y finalmente se entrar en un
bucle en el que se fije una alarma de 1 segundo todo el rato. El resultado es que se mostrar un mensaje RIIIIIIIIING
a los 5 segundos, luego a los 3 segundos y despus cada segundo:
UNAN-Leon
Sistemas Operativos
main()
{
pid_t padre, hijo;
padre = getpid();
signal( SIGUSR1, trapper );
if ( (hijo=fork()) == 0 )
{ /* hijo */
sleep(1);
kill(padre, SIGUSR1);
sleep(1);
kill(padre, SIGUSR1);
sleep(1);
kill( padre, SIGUSR1);
sleep(1);
kill(padre, SIGKILL);
exit(0);
}
else
{ /* padre */
for (;;);
}
return 0;
}
EJERCICIOS
1. Realice un programa que cree un proceso hijo, deber entrar en un bucle infinito y esperar. El proceso padre
deber matar a su proceso hijo despus de 10 segundos. Y aparecer por pantalla el PID del padre, el PID del
hijo y un mensaje indicando la muerte del hijo y la finalizacin del padre.
2. Cree un proceso que nos informe de la cantidad de veces que se pulsa (CTRL+C) en un periodo de 25
segundos.
3. Realice un programa que mediante el uso de la seal SIGALARM realice lo siguiente. Un programa espera por
una cadena introducida por teclado. Si pasados 20 segundos esta accin no se realiza, el proceso deber
decirTermino el tiempo de espera FIN.
4. Implementar un programa que cree un proceso hijo, el cual deber imprimir su PID, y PPID. El padre deber
esperar su finalizacin y capturar la seal de muerte del proceso hijo e imprimir el mensaje MI HIJO HA
MUERTO.