En un sistema, los procesos que se ejecutan simultáneamente
interactúan entre sí. Esta interacción se produce incluso en el caso de
procesos independientes, es decir, los que no necesitan cooperar para completar
sus tareas.
Esto ocurre cuando varios procesos quieren acceder a los
mismos recursos, y para resolver esta situación el SO dispone de un gestor de
procesos para determinar el orden de acceso a estos recursos.
Las señales pueden considerarse un tipo de mensajes, aunque,
comparado con otros medios de comunicación (sockets,
pipes, etc.) resultan un mecanismo más pobre porque no permiten transmitir
datos, pero sí proporcionan dos servicios fundamentales:
è
Defensa del proceso establecido frente a
incidencias comunicadas por el kernel. Si las señales no son gestionadas (o
ignoradas, o capturadas) por el proceso al que van dirigidas, éste concluye
inmediatamente lo que puede provocar una pérdida irrecuperable de datos.
è
Mecanismo de comunicación entre dos procesos.
Resulta útil y sencillo para avisar a un proceso de la aparición de eventos
excepcionales, aunque no debe ser la forma habitual de que se comuniquen. Por
ejemplo, cuando un usuario desea interrumpir un proceso de impresión que ha
mandado por error.
Es decir, el uso de señales es un método sencillo de aviso
de incidencias ya sea por circunstancias del propio proceso o por la
intervención del otro.
Las señales pueden llegar en cualquier momento, por lo que
los procesos no pueden limitarse a verificar una variable para comprobar si ha
llegado una señal, sino que deben lanzar una rutina de tratamiento de la señal
para gestionar automáticamente su recepción en el momento que aparezca.
Hay distintos tipos de señales, que podemos ver en éste
gráfico
Una de las principales utilidades de las señales es la
sincronización entre dos procesos. Esto es, un proceso realizará un conjunto de
instrucciones cuando otro proceso se lo indique, o paralizará su actividad
hasta que se cumpla una condición determinada, teniendo en cuenta la región crítica, que sería el trozo de
código de un proceso que puede interferir con otro proceso.
Esta secuencia de acciones se ejecutan en paralelo y pueden
repetirse infinitamente, con lo que el bucle tendría una traza tal que así:
1.
El proceso padre crea un proceso hijo
2.
El proceso padre ejecuta un conjunto de acciones
a partir de las cuales se desea que el proceso hijo continúe
3.
Si no hay error y se desea que el hijo ejecute
sus acciones:
3.1.
El proceso padre envía una señal SIGUSR1 al hijo
para que comiece.
3.2.
El proceso hijo realiza un conjunto de acciones
3.3.
El proceso hijo envía la señal SIGUSR1 al padre
3.4.
Volvemos a 2
4.
En caso contrario:
4.1.
El proceso padre envía una señal SIGTERM al hijo
para que termine
4.2.
El proceso hijo termina
4.3.
El proceso padre termina
El comando kill en
Linux envía una señal a un proceso, indicando primero la señal y luego el PID.
Por ejemplo,termina kill -9
PID el proceso con el PID que hemos indicado.
Para crear una señal en C debemos tener en cuenta la
estructura de las funciones que podemos utilizar
Esto envía una señal invocando a un manejador por puntero
para que la reciba y la trate:
void (*signal(int señal,
void(*Func)(int)(int));
Esto detiene el proceso hasta recibir una señal.
int pause(void);
Aquí dormimos el proceso en un tiempo indicado en segundos.
También se interrumpe si recibe una señal.
unsigned int
sleep(unsigned int seconds);
Y esto envía una señal para matar un proceso.
int kill(int pid,
int señal);
Veamos un ejemplo de como un padre invoca a una señal que
recibirá el hijo.
#include
<stdio.h>
#include
<fcntl.h>
#include
<unistd.h>
#include
<signal.h>
#include
<stdlib.h>
void manejador (int
segnal){
printf("Hijo recibe señal... %d
\n", segnal);
}
int main(){
int pid_hijo;
pid_hijo = fork(); // creamos hijo
switch(pid_hijo){
case -1:
printf("ERROR AL CREAR EL
PROCESO HIJO... \n");
exit(-1);
break;
case 0: // HIJO
signal(SIGUSR1, manejador); //
Invocamos al puntero al que referencia la función
while(1){};
break;
default: // PADRE
sleep(1);
kill(pid_hijo, SIGUSR1);
sleep(1);
kill(pid_hijo, SIGUSR1);
sleep(1);
break;
}
return 0;
}
marica
ResponderEliminar