En la programación de sistemas Linux, las señales son un mecanismo importante para la comunicación y el control entre procesos. Cuando ocurre un evento determinado, como que el usuario presione las teclas Ctrl+C, el sistema operativo envía una señal al proceso, que el proceso puede captar y manejar en consecuencia. Este blog presentará la clasificación, captura y procesamiento de señales, así como el funcionamiento predeterminado de las señales. Espero que a través de este blog puedan comprender mejor el concepto y la aplicación de señales en la programación del sistema Linux.
Directorio de artículos
1. ¿Qué es una señal?
En los sistemas Linux, las señales son un mecanismo para la comunicación y el control entre procesos. Cuando ocurre un evento, el kernel envía una señal al proceso, y el proceso puede elegir capturar y procesar la señal, o utilizar el método de procesamiento predeterminado.
Las señales pueden ser activadas por varios eventos, como que el usuario presione Ctrl+C
una tecla, un error en el proceso o la salida de un proceso hijo. Cada señal tiene un número único y un comportamiento predeterminado predefinido.
2. Clasificación de señales
-
Señales Estándar : Estas señales están numeradas entre 1 y 31 y están definidas en el estándar POSIX. Por ejemplo, la señal SIGINT (número 2) se activa cuando el usuario presiona la tecla Ctrl+C, y la señal SIGTERM (número 15) es la señal utilizada para finalizar el proceso.
-
Señales en tiempo real : Estas señales están numeradas entre 32 y 63 y también están definidas en el estándar POSIX. Las señales en tiempo real proporcionan mayor prioridad y una sincronización de disparo más precisa.
-
Señales definidas por el usuario : estas señales pueden ser definidas por los usuarios y sus números son mayores que 64.
3. Método de procesamiento de señales
-
Ignorar (Ignorar) : El proceso puede optar por ignorar una señal específica, de modo que cuando ocurra la señal, el proceso no hará nada. Sin embargo, algunas señales no se pueden ignorar, como SIGKILL y SIGSTOP.
-
Captura : un proceso puede captar una señal registrando un controlador de señales. Cuando ocurre una señal, el kernel llamará a la función de manejo de señales registrada para manejar la señal.
-
Realizar acción predeterminada (Acción predeterminada) : cada señal tiene un comportamiento predeterminado predefinido, como finalizar el proceso, finalizar el proceso y generar un archivo de volcado de núcleo, etc.
4. Captura y procesamiento de señales.
4.1signal
Rol : signal
La función se utiliza para capturar y procesar señales.
Prototipo :
#include <signal.h>
void (*signal(int signum, void (*handler)(int)))(int);
Parámetros :
signum
: El número de señal a capturar.handler
: Puntero a la función del controlador de señales.
Valor de retorno : Devuelve el puntero a la función de procesamiento anterior de la señal. Devuelve si ocurre un error SIG_ERR
.
Ejemplo : a continuación se muestra un ejemplo que demuestra cómo usar signal
una función para capturar y manejar la señal SIGINT (el usuario presiona las teclas Ctrl+C).
#include <stdio.h>
#include <signal.h>
void sigint_handler(int signum) {
printf("Received SIGINT signal\n");
}
int main() {
// 注册SIGINT信号的处理函数
signal(SIGINT, sigint_handler);
printf("Press Ctrl+C to send SIGINT signal\n");
while (1) {
// 无限循环,等待信号的发生
}
return 0;
}
Explicación de ejemplo :
- En el ejemplo anterior, definimos una
sigint_handler
función de manejo de señales llamada. Cuando se recibe una señal SIGINT, se llama a esta función y se imprime un mensaje. - En
main
la función, usamossignal
la función para registrarsigint_handler
la función como controlador de la señal SIGINT. De esta manera, cuando el usuario presiona la tecla Ctrl+C, el sistema operativo enviará una señal SIGINT al proceso y llamará asigint_handler
una función para manejar la señal. - En
main
el bucle infinito de la función, esperamos a que se produzca la señal. De esta manera, el proceso se ejecuta hasta que recibe una señal SIGINT u otra señal de terminación. - Cuando presionamos la tecla Ctrl+C, se activará la señal SIGINT, el proceso llamará
sigint_handler
a la función e imprimirá un mensaje.
4.2sigaction
Rol : sigaction
La función es otra forma de capturar y procesar señales, signal
que proporciona más flexibilidad y confiabilidad que la función.
Prototipo :
#include <signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
Parámetros :
signum
: El número de señal a capturar.act
:struct sigaction
puntero a una estructura que especifica el nuevo método de manejo de señales.oldact
: Unstruct sigaction
puntero a una estructura utilizada para guardar el método de procesamiento de señal anterior.
Valor de retorno : si tiene éxito, devuelve 0; en caso de error, devuelve -1.
Ejemplo : a continuación se muestra un ejemplo que demuestra cómo usar sigaction
una función para capturar y manejar la señal SIGINT (el usuario presiona las teclas Ctrl+C).
#include <stdio.h>
#include <signal.h>
void sigint_handler(int signum) {
printf("Received SIGINT signal\n");
}
int main() {
struct sigaction sa;
sa.sa_handler = sigint_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
// 注册SIGINT信号的处理函数
sigaction(SIGINT, &sa, NULL);
printf("Press Ctrl+C to send SIGINT signal\n");
while (1) {
// 无限循环,等待信号的发生
}
return 0;
}
Explicación de ejemplo :
- En el ejemplo anterior, definimos una
sigint_handler
función de manejo de señales llamada. Cuando se recibe una señal SIGINT, se llama a esta función y se imprime un mensaje. - Creamos una
struct sigaction
estructurasa
ysigint_handler
especificamos la función como controlador de señal. sigemptyset
Inicializado con una funciónsa.sa_mask
, lo que significa que no es necesario bloquear otras señales al procesar la señal SIGINT.sa.sa_flags
Establezca en 0 para indicar que no se requieren indicadores especiales.- Utilice
sigaction
una función parasa
registrar una estructura sobre cómo manejar la señal SIGINT. - En
main
el bucle infinito de la función, esperamos a que se produzca la señal. De esta manera, el proceso se ejecuta hasta que recibe una señal SIGINT u otra señal de terminación. - Cuando presionamos la tecla Ctrl+C, se activará la señal SIGINT, el proceso llamará
sigint_handler
a la función e imprimirá un mensaje.
5. Acciones predeterminadas para señales
Si no se capta una señal o el controlador de señales captadas regresa, el proceso realizará la acción predeterminada para la señal.
Por ejemplo, un proceso finaliza de forma predeterminada cuando se recibe una señal SIGTERM. A continuación se muestra un ejemplo que demuestra el funcionamiento predeterminado de la señal SIGTERM:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void sigterm_handler(int signum) {
printf("Received SIGTERM signal\n");
}
int main() {
// 注册SIGTERM信号的处理函数
signal(SIGTERM, sigterm_handler);
printf("Press Ctrl+C to send SIGTERM signal\n");
while (1) {
// 无限循环,等待信号的发生
}
return 0;
}
En el ejemplo anterior, captamos la señal SIGTERM y registramos sigterm_handler
la función como controlador. Cuando se recibe una señal SIGTERM, se llama a esta función y se imprime un mensaje.
Resumir
Las señales son un mecanismo para la comunicación y el control entre procesos en los sistemas Linux. Podemos manejar la señal capturándola y registrando una función de controlador. Al manejar una señal, podemos optar por ignorarla, captarla o realizar una acción predeterminada.