LINUX

Manejo de señales en Linux a través de la función signal ()

En la parte 1 de esta serie sobre señales de Linux, discutimos los fundamentos de las señales en Linux. En este artículo, discutiremos los aspectos prácticos del manejo de señales en Linux a través del señal() función. Todas las explicaciones irán acompañadas de ejemplos prácticos.

c función de señal

Controladores de señales

Un manejador de señales es una función especial (definida en el código del programa de software y registrada con el kernel) que se ejecuta cuando llega una señal en particular. Esto provoca la interrupción del proceso de ejecución actual y todos los registros actuales también se guardan. El proceso interrumpido se reanuda una vez que regresa el manejador de señales.

La función signal ()

La forma más sencilla de registrar la función del manejador de señales con el kernel es usando el señal() función.

Aquí está la sintaxis de señal() función:

#include <signal.h>

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);

Entonces puede ver que un manejador de señales es una función que acepta un argumento entero pero devuelve vacío. El manejador de señales se puede registrar con el kernel usando el señal() función (descrita anteriormente) que acepta un número de señal particular y el nombre de la función del controlador de señal (aunque puede haber otros valores para el segundo argumento, pero los discutiremos más adelante).

A continuación se muestra un ejemplo práctico de manejo de señales en Linux a través del señal() función:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

void sig_handler(int sig_num)
{
if(sig_num == SIGINT)
{
printf("n Caught the SIGINT signaln");
}
else
{
printf("n Caught the signal number [%d]n", sig_num);
}

// Do all the necessary clean-up work here

exit(sig_num);
}

int main(void)
{
//Register signal handler through the signal() function
signal(SIGINT, sig_handler);

while(1)
{
//simulate a delay -- as if the program is doing some other stuff
sleep(1);
}

return 0;
}

En el código del programa que se muestra arriba:

  • Dentro de la función main (), la función signal () se usa para registrar un manejador (sig_handler ()) para SIGNO señal.
  • El bucle while simula un retardo infinito. Entonces, el programa espera FIRMARLO señal infinitamente.
  • El manejador de señales ‘sig_handler’ imprime una declaración de depuración verificando si la señal deseada es SIGNO O no.
  • El manejador de señales se usa principalmente para hacer toda la limpieza y otras cosas relacionadas después de que se envía una señal a un proceso.

Aquí está el resultado de este programa:

$ ./sig_example
^C
Caught the SIGINT signal

Entonces puede ver que el programa (sig_example) se ejecutó y luego la señal SIGNO se le pasa presionando la combinación de teclas Ctrl + c. Como se puede ver en la impresión de depuración en la salida, el manejador de señales se ejecutó tan pronto como la señal SIGNO fue entregado al proceso.

Disposición de una señal

Para comprender el concepto de disposición de una señal, revisemos la declaración de función de señal:

sighandler_t signal(int signum, sighandler_t handler);

El segundo argumento de la función signal () se conoce como disposición de una señal. A partir de ahora, aprendimos que el segundo argumento es una función de manejo de señales, pero este no es el único tipo de método de disposición de señales. Otras formas de disposición de una señal son especificar SIG_IGN o SIG_DFL como segundo argumento de la función de señal.

Si la disposición se establece en SIG_IGN luego la señal (pasada como primer argumento a señal() función) se ignora y no se entrega al proceso, pero si la disposición se establece en SIG_DFL entonces se toma la acción predeterminada correspondiente a esa señal.

A continuación, se muestra un ejemplo de un código que ignora la SIGNO señal:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

int main(void)
{
//Register signal handler through the signal() function
signal(SIGINT, SIG_IGN);

while(1)
{
//simulate a delay -- as if the program is doing some other stuff
sleep(1);
}

return 0;
}

Entonces puede ver que ahora no hay una función de controlador de señal, ya que el segundo argumento de la función de señal se reemplaza con SIG_IGN.

Aquí está el resultado de este programa:

$ ./sig_example
^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C^C

Entonces puede ver que a pesar de presionar repetidamente Ctrl + c, el proceso no se vio afectado de ninguna manera. Esto se debe a que la señal SIGNO (generado cuando Ctrl + c se presiona) se ignora.

Del mismo modo, aquí hay un código de programa que deja SIGNO a su acción predeterminada:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>

int main(void)
{
//Register signal handler through the signal() function
signal(SIGINT, SIG_DFL);

while(1)
{
//simulate a delay -- as if the program is doing some other stuff
sleep(1);
}

return 0;
}

Entonces puede ver que el segundo argumento de la función de señal (en el código que se muestra arriba) se reemplaza con SIG_DFL en este caso.

Y aquí está el resultado de este programa:

$ ./sig_example
^C
$

Entonces puedes ver que presionando Ctrl + c terminó el proceso porque la acción predeterminada de SIGNO es terminar el proceso.

Limitaciones de la función signal ()

Aunque el señal() La función es la forma más antigua y fácil de manejar señales, tiene un par de limitaciones importantes:

  • Otras señales no son bloqueadas por la función signal () mientras el manejador de señales se está ejecutando para la señal actual. Esto puede producir resultados no deseados.
  • La acción de la señal para una señal en particular se restablece a su valor predeterminado, es decir, SIG_DFL tan pronto como se entregue la señal. Esto significa que incluso si el manejador de señales establece nuevamente la acción de la señal como el primer paso, existe una posible ventana de tiempo en la que la señal puede ocurrir nuevamente mientras su acción se establece en SIG_DFL.

Debido a estas importantes limitaciones, ahora se recomienda utilizar la función sigaction () que supera todas estas limitaciones.

Publicaciones relacionadas

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Botón volver arriba
Cerrar