En informática, sigaction
es una función API definida por POSIX para dar al programador acceso a cuál debe ser el comportamiento de un programa al recibir señales específicas del sistema operativo .
En los sistemas operativos tipo Unix , una de las formas de comunicación entre procesos es a través de señales. Cuando una unidad de ejecución ( proceso o hilo ) recibe una señal del sistema operativo, debería reaccionar de alguna manera definida por la hoja de datos y el significado convencional de esta señal (es decir, volcando sus datos, deteniendo la ejecución, sincronizando algo...).
La sigaction()
llamada al sistema se utiliza para declarar el comportamiento del programa en caso de que reciba una señal particular no reservada para el sistema. Esto se hace proporcionando junto con la llamada al sistema una estructura que contiene, entre otros, un puntero de función a la rutina de manejo de señales. Algunas señales predefinidas (como SIGKILL
) tienen un comportamiento bloqueado que es manejado por el sistema y no se puede anular con dichas llamadas al sistema.
El estándar POSIX requiere que la estructura sigaction se defina como se muestra a continuación en el archivo de encabezado <signal.h> y debe contener al menos los siguientes campos:
struct sigaction { void ( * sa_handler )( int ); /* dirección del manejador de señales */ sigset_t sa_mask ; /* señales adicionales para bloquear */ int sa_flags ; /* opciones de señal */ /* manejador de señales alternativo */ void ( * sa_sigaction )( int , siginfo_t * , void * ); };
Las implementaciones tienen la libertad de definir campos adicionales, posiblemente no portables. El miembro sa_handler especifica la dirección de una función que se llamará cuando el proceso reciba la señal. El número de señal se pasa como un argumento entero a esta función. El miembro sa_mask especifica señales adicionales que se bloquearán durante la ejecución del manejador de señales. sa_mask debe inicializarse con sigemptyset(3). El miembro sa_flags especifica algunos indicadores adicionales. sa_sigaction es un manejador de señales alternativo con un conjunto diferente de parámetros. Solo se debe especificar un manejador de señales, ya sea sa_handler o sa_sigaction. Si se desea utilizar sa_sigaction en lugar de sa_handler, se debe establecer el indicador SA_SIGINFO.
La sigaction()
función proporciona una interfaz para señales confiables en reemplazo de la signal()
función no confiable. Los controladores de señales instalados por la signal()
interfaz se desinstalarán inmediatamente antes de la ejecución del controlador. Por lo tanto, los controladores permanentes deben reinstalarse mediante una llamada a signal()
durante la ejecución del controlador, lo que provoca falta de confiabilidad en caso de que se reciba una señal del mismo tipo durante la ejecución del controlador pero antes de la reinstalación. Los controladores instalados por la sigaction()
interfaz se pueden instalar de forma permanente y se puede bloquear un conjunto personalizado de señales durante la ejecución del controlador. Estas señales se desbloquearán inmediatamente después de la finalización normal del controlador (pero no en caso de una finalización anormal como una excepción de C++).
En C++, la try {/* ... */} catch {/* ... */}
estructura de programación puede basarse en señalización (según las plataformas anfitrionas). Para catch
traducir las señales a excepciones de C++, pueden ser necesarios modificadores de compilador especiales en algunas plataformas, como -fnon-call-exceptions
GCC y el compilador Intel C. [1]
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/wait.h> #include <signal.h> #define NUMCHLDS 10vacío sigchld_handler ( int , siginfo_t * , vacío * ); sig_atomic_tnexitechlds = 0 ; int principal ( int argc , char * argv []) { estructura sigaction act ; memset ( & act , 0 , sizeof ( struct sigaction )); sigemptyset ( & act . sa_mask ); acto . sa_sigaction = sigchld_handler ; actuar .sa_flags = SA_SIGINFO ; si ( -1 == sigaction ( SIGCHLD , & act , NULL )) { perror ( "sigaction()" ); salir ( EXIT_FAILURE ); } for ( int i = 0 ; i < NUMCHLDS ; i ++ ) { switch ( fork ()) { case 0 : /* * Las implementaciones de SO más antiguas que no implementan correctamente * la estructura siginfo truncarán el código de salida * enmascarándolo con 0xFF. */ return 1234567890 ; /* NOTREACHED */ case -1 : write ( STDERR_FILENO , "fork ERROR!" , 11 ); exit ( EXIT_FAILURE ); /* NOTREACHED */ default : printf ( "Hijo creado \n " ); } } mientras ( 1 ) { si ( nexitedchlds < NUMCHLDS ) pausa (); de lo contrario salir ( EXIT_SUCCESS ); } /* NO ALCANZADO */ devolver 0 ; } void sigchld_handler ( int signo , siginfo_t * sinfo , void * contexto ) { pid_t proc ; mientras (( proc = waitpid ( -1 , NULL , WNOHANG )) > 0 ) { /* señal del hilo principal */ nexitedchlds ++ ; /* * nota: printf() no es seguro para señales. * no lo use en un manejador de señales. * si_code es el código de salida completo de 32 bits del hijo (ver también waitid()). */ printf ( "sinfo->si_pid = %ld \n proc = %ld \n código de salida %d motivo de salida %d \n " , ( long ) sinfo -> si_pid , ( long ) proc , sinfo -> si_status , sinfo -> si_code ); } }