Forma de comunicación entre procesos en sistemas informáticos
Las señales son mensajes estandarizados que se envían a un programa en ejecución para activar un comportamiento específico, como el cierre o el manejo de errores. Son una forma limitada de comunicación entre procesos (IPC), que se utiliza normalmente en sistemas operativos Unix , similares a Unix y otros compatibles con POSIX .
Una señal es una notificación asincrónica enviada a un proceso o a un subproceso específico dentro del mismo proceso para notificarle un evento. Los usos comunes de las señales son interrumpir, suspender, terminar o matar un proceso. Las señales se originaron en Bell Labs Unix de la década de 1970 y luego se especificaron en el estándar POSIX .
Cuando se envía una señal, el sistema operativo interrumpe el flujo normal de ejecución del proceso de destino para entregar la señal. La ejecución se puede interrumpir durante cualquier instrucción no atómica . Si el proceso ha registrado previamente un manejador de señales , se ejecuta esa rutina. De lo contrario, se ejecuta el manejador de señales predeterminado.
Los programas integrados pueden encontrar señales útiles para las comunicaciones entre procesos, ya que las señales se destacan por su eficiencia algorítmica .
Las señales son similares a las interrupciones , la diferencia es que las interrupciones son mediadas por la CPU y manejadas por el núcleo , mientras que las señales son mediadas por el núcleo (posiblemente a través de llamadas al sistema) y manejadas por procesos individuales . [ cita requerida ] El núcleo puede pasar una interrupción como señal al proceso que la causó (los ejemplos típicos son SIGSEGV , SIGBUS , SIGILL y SIGFPE).
Historia
Envío de señales
La llamada al sistema kill (2) envía una señal específica a un proceso específico, si los permisos lo permiten. De manera similar, el comando kill(1) permite que un usuario envíe señales a los procesos. La función de biblioteca raise(3) envía la señal especificada al proceso actual.
Excepciones como la división por cero , la violación de segmentación (SIGSEGV) y la excepción de punto flotante (SIGFPE) provocarán un volcado de núcleo y finalizarán el programa.
El núcleo puede generar señales para notificar eventos a los procesos. Por ejemplo, SIGPIPE se generará cuando un proceso escriba en una tubería que haya sido cerrada por el lector; de manera predeterminada, esto hace que el proceso finalice, lo que resulta conveniente al construir tuberías de shell .
Al escribir determinadas combinaciones de teclas en la terminal de control de un proceso en ejecución, el sistema le envía determinadas señales: [3]
- Ctrl-C (en Unix antiguos, DEL) envía una señal INT ("interrupción", SIGINT); de forma predeterminada, esto hace que el proceso finalice.
- Ctrl-Z envía una señal TSTP ("terminal stop", SIGTSTP ); por defecto, esto hace que el proceso suspenda la ejecución. [4]
- Ctrl-\ envía una señal QUIT (SIGQUIT); de manera predeterminada, esto hace que el proceso finalice y descargue el núcleo.
- Ctrl-T (no compatible con todos los UNIX) envía una señal INFO (SIGINFO); de manera predeterminada, y si el comando lo admite, esto hace que el sistema operativo muestre información sobre el comando en ejecución. [5]
Estas combinaciones de teclas predeterminadas con los sistemas operativos modernos se pueden cambiar con el comando stty .
Manejo de señales
Los controladores de señales se pueden instalar con la llamada al sistema signal(2) o sigaction(2) . Si no se instala un controlador de señales para una señal en particular, se utiliza el controlador predeterminado. De lo contrario, se intercepta la señal y se invoca el controlador de señales. El proceso también puede especificar dos comportamientos predeterminados, sin crear un controlador: ignorar la señal (SIG_IGN) y utilizar el controlador de señales predeterminado (SIG_DFL). Hay dos señales que no se pueden interceptar ni controlar: SIGKILL y SIGSTOP .
Riesgos
El manejo de señales es vulnerable a las condiciones de carrera . Como las señales son asincrónicas, se puede enviar otra señal (incluso del mismo tipo) al proceso durante la ejecución de la rutina de manejo de señales.
La llamada sigprocmask(2) se puede utilizar para bloquear y desbloquear la entrega de señales. Las señales bloqueadas no se envían al proceso hasta que se desbloquean. Las señales que no se pueden ignorar (SIGKILL y SIGSTOP) no se pueden bloquear.
Las señales pueden provocar la interrupción de una llamada del sistema en curso, dejando en manos de la aplicación la tarea de gestionar un reinicio no transparente .
Los manejadores de señales deben escribirse de una manera que no resulte en efectos secundarios no deseados, por ejemplo, alteración de errno , alteración de máscara de señal, cambio de disposición de señal y otros cambios de atributos de proceso globales . El uso de funciones no reentrantes , por ejemplo, malloc o printf , dentro de los manejadores de señales también es inseguro. En particular, la especificación POSIX y la página del manual de Linux signal (7) requieren que todas las funciones del sistema llamadas directa o indirectamente desde una función de señal sean seguras para señales asíncronas . [6] [7] La página del manual signal-safety(7) proporciona una lista de tales funciones del sistema seguras para señales asíncronas (prácticamente las llamadas del sistema ); de lo contrario, es un comportamiento indefinido . [8] Se sugiere simplemente establecer alguna variable en un manejador de señales y probarla en otro lugar. [9]volatile sig_atomic_t
Los manejadores de señales pueden, en cambio, poner la señal en una cola y regresar inmediatamente. El hilo principal continuará entonces "ininterrumpidamente" hasta que se tomen señales de la cola, como en un bucle de eventos . "Ininterrumpida" aquí significa que las operaciones que se bloquean pueden regresar prematuramente y deben reanudarse , como se mencionó anteriormente. Las señales deben procesarse desde la cola en el hilo principal y no por grupos de trabajadores , ya que eso reintroduce el problema de la asincronicidad. Sin embargo, la gestión de una cola no es posible de una manera segura para señales asíncronas solo con sig_atomic_t , ya que solo se garantiza que las lecturas y escrituras individuales a dichas variables sean atómicas, no incrementos o (obtención y) decrementos, como se requeriría para una cola. Por lo tanto, efectivamente, solo una señal por manejador se puede poner en cola de manera segura con sig_atomic_t hasta que se haya procesado.
Relación con excepciones de hardware
La ejecución de un proceso puede generar la generación de una excepción de hardware , por ejemplo, si el proceso intenta dividir por cero o incurre en un error de página .
En sistemas operativos tipo Unix , este evento cambia automáticamente el contexto del procesador para comenzar a ejecutar un controlador de excepciones del núcleo . En caso de algunas excepciones, como un error de página , el núcleo tiene suficiente información para manejar completamente el evento y reanudar la ejecución del proceso.
Sin embargo, el núcleo no puede procesar otras excepciones de forma inteligente y, en su lugar, debe aplazar la operación de manejo de la excepción al proceso que ha producido el error. Esta postergación se logra mediante el mecanismo de señal, en el que el núcleo envía al proceso una señal correspondiente a la excepción actual. Por ejemplo, si un proceso intentara dividir un número entero por cero en una CPU x86 , se generaría una excepción de error de división y haría que el núcleo enviara la señal SIGFPE al proceso.
De manera similar, si el proceso intentara acceder a una dirección de memoria fuera de su espacio de direcciones virtuales , el núcleo notificaría al proceso sobre esta violación a través de una señal SIGSEGV ( señal de violación de segmentación ). La asignación exacta entre los nombres de las señales y las excepciones obviamente depende de la CPU, ya que los tipos de excepciones difieren entre arquitecturas.
Señales POSIX
La lista que aparece a continuación documenta las señales especificadas en la Especificación Única de Unix . Todas las señales se definen como constantes macro en el <signal.h>
archivo de encabezado. El nombre de la constante macro consta de un prefijo "SIG" seguido de un nombre mnemotécnico para la señal.
Un proceso puede definir cómo manejar las señales POSIX entrantes . Si un proceso no define un comportamiento para una señal, se utiliza el controlador predeterminado para esa señal. La siguiente tabla enumera algunas acciones predeterminadas para sistemas UNIX compatibles con POSIX, como FreeBSD , OpenBSD y Linux .
- Número portátil:
- Para la mayoría de las señales, el número de señal correspondiente está definido por la implementación. Esta columna enumera los números especificados en el estándar POSIX. [10]
- Acciones explicadas:
- Terminar : finalización anormal del proceso. El proceso finaliza con todas las consecuencias de _exit(), excepto que el estado disponible para wait() y waitpid() indica una finalización anormal mediante la señal especificada.
- Terminar (volcado de memoria) : terminación anormal del proceso. Además, pueden ocurrir acciones de terminación anormales definidas por la implementación, como la creación de un archivo de memoria.
- Ignorar – Ignorar la señal.
- Detener – Detener (o suspender) el proceso.
- Continuar – Continúa el proceso si se detuvo; de lo contrario, ignora la señal.
- SIGABRT ySIGIOTA
- La señal SIGABRT se envía a un proceso para indicarle que debe abortar , es decir, que debe terminar. La señal suele ser iniciada por el propio proceso cuando llama a
abort()
una función de la biblioteca estándar de C , pero puede enviarse al proceso desde fuera como cualquier otra señal. - SIGIOT indica que la CPU ha ejecutado una instrucción "trampa" explícita (sin una función definida) o una instrucción no implementada (cuando la emulación no está disponible).
- Nota: "trampa de entrada/salida" es un nombre inapropiado para cualquier instrucción de "trampa" de CPU. El término refleja el uso temprano de dichas instrucciones, predominantemente para implementar funciones de E/S, pero no están inherentemente vinculadas a la E/S del dispositivo y pueden usarse para otros fines, como la comunicación entre hosts virtuales y reales.
- SIGIOT y SIGABRT suelen ser la misma señal y la recepción de esa señal puede indicar cualquiera de las condiciones anteriores.
- Señalar ,SIGVTALRM ySIGPROF
- Las señales SIGALRM, SIGVTALRM y SIGPROF se envían a un proceso cuando se alcanza el límite de tiempo correspondiente. El proceso establece estos límites de tiempo llamando a
alarm
o setitimer
. El límite de tiempo para SIGALRM se basa en el tiempo real o de reloj; SIGVTALRM se basa en el tiempo de CPU utilizado por el proceso; y SIGPROF se basa en el tiempo de CPU utilizado por el proceso y por el sistema en su nombre (conocido como temporizador de creación de perfiles ). En algunos sistemas, SIGALRM puede utilizarse internamente por la implementación de la sleep
función. - SIGBUS
- La señal SIGBUS se envía a un proceso cuando provoca un error de bus . Las condiciones que provocan el envío de la señal son, por ejemplo, una alineación incorrecta del acceso a la memoria o una dirección física inexistente.
- SEGURIDAD
- La señal SIGCHLD se envía a un proceso cuando un proceso secundario finaliza , se detiene o se reanuda después de haber sido detenido. Un uso común de la señal es indicarle al sistema operativo que limpie los recursos utilizados por un proceso secundario después de su finalización sin una llamada explícita a la
wait
llamada del sistema. - Control de señal
- La señal SIGCONT indica al sistema operativo que continúe (reinicie) un proceso que se detuvo previamente con la señal SIGSTOP o SIGTSTP. Un uso importante de esta señal es el control de tareas en el shell de Unix .
- SIGFPE
- La señal SIGFPE se envía a un proceso cuando se ha detectado una condición excepcional (pero no necesariamente errónea) en el hardware de aritmética de punto flotante o entero. Esto puede incluir una división por cero , un desbordamiento o subdesbordamiento de punto flotante, un desbordamiento de entero , una operación no válida o un cálculo inexacto. El comportamiento puede variar según el hardware.
- SUSPIRO
- La señal SIGHUP se envía a un proceso cuando su terminal de control está cerrada. Originalmente, se diseñó para notificar al proceso una caída de la línea serial (un bloqueo ). En los sistemas modernos, esta señal generalmente significa que el pseudo terminal o terminal virtual de control se ha cerrado. [11] Muchos daemons (que no tienen terminal de control) interpretan la recepción de esta señal como una solicitud para recargar sus archivos de configuración y vaciar/reabrir sus archivos de registro en lugar de salir. [12] nohup es un comando para hacer que un comando ignore la señal.
- SIGIL
- La señal SIGILL se envía a un proceso cuando intenta ejecutar una instrucción ilegal , malformada, desconocida o privilegiada .
- SEÑAL
- La señal SIGINT se envía a un proceso por medio de su terminal de control cuando un usuario desea interrumpir el proceso. Esto se inicia típicamente presionando Ctrl+C , pero en algunos sistemas, se puede utilizar el carácter " eliminar " o la tecla " interrumpir ". [13]
- Matanza de señales
- La señal SIGKILL se envía a un proceso para provocar su finalización inmediata ( kill ). A diferencia de SIGTERM y SIGINT, esta señal no se puede detectar ni ignorar, y el proceso receptor no puede realizar ninguna limpieza al recibirla. Se aplican las siguientes excepciones:
- Los procesos zombies no pueden eliminarse porque ya están muertos y esperando que sus procesos padres los recopilen.
- Los procesos que están en estado bloqueado no morirán hasta que se activen nuevamente.
- El proceso init es especial: no recibe señales que no desea manejar y, por lo tanto, puede ignorar SIGKILL. [14] Una excepción a esta regla es cuando init está trazado en Linux. [15] [16]
- Es posible que un proceso que se encuentra inactivo no finalice (y libere sus recursos) incluso cuando se le envía SIGKILL. Este es uno de los pocos casos en los que puede ser necesario reiniciar un sistema UNIX para resolver un problema de software temporal.
- SIGKILL se utiliza como último recurso al finalizar procesos en la mayoría de los procedimientos de apagado del sistema si no sale voluntariamente en respuesta a SIGTERM. Para acelerar el procedimiento de apagado de la computadora, Mac OS X 10.6, también conocido como Snow Leopard , enviará SIGKILL a las aplicaciones que se hayan marcado como "limpias", lo que dará como resultado tiempos de apagado más rápidos sin, presumiblemente, efectos nocivos. [17] El comando
killall -9
tiene un efecto similar, aunque peligroso, cuando se ejecuta, por ejemplo, en Linux; no permite que los programas guarden los datos no guardados. Tiene otras opciones y, sin ninguna, utiliza la señal SIGTERM más segura. - SIGPIPE
- La señal SIGPIPE se envía a un proceso cuando intenta escribir en una tubería sin un proceso conectado al otro extremo.
- ENCUESTA DE SIG
- La señal SIGPOLL se envía cuando se produce un evento en un descriptor de archivo observado explícitamente. [18] Su uso eficaz conduce a la realización de solicitudes de E/S asincrónicas , ya que el núcleo sondeará el descriptor en lugar del llamador. Proporciona una alternativa al sondeo activo .
- SIGRTMIN aSIGRTMÁXIMO
- Las señales SIGRTMIN a SIGRTMAX están pensadas para utilizarse con fines definidos por el usuario. Son señales en tiempo real .
- SALIRSE
- La señal SIGQUIT es enviada a un proceso por su terminal de control cuando el usuario solicita que el proceso salga y realice un volcado de núcleo .
- SIGSEGV
- La señal SIGSEGV se envía a un proceso cuando éste realiza una referencia de memoria virtual no válida, o un fallo de segmentación , es decir, cuando realiza una violación de segmentación . [19]
- PARADA DE SEÑAL
- La señal SIGSTOP instruye al sistema operativo a detener un proceso para reanudarlo más tarde.
- SIGSYS
- La señal SIGSYS se envía a un proceso cuando pasa un argumento incorrecto a una llamada del sistema . En la práctica, este tipo de señal rara vez se encuentra ya que las aplicaciones dependen de bibliotecas (por ejemplo, libc ) para realizar la llamada por ellas. SIGSYS puede ser recibida por aplicaciones que violen las reglas de seguridad Seccomp de Linux configuradas para restringirlas. SIGSYS también se puede utilizar para emular llamadas del sistema externas, por ejemplo, emular llamadas del sistema de Windows en Linux. [20]
- TÉRMINO DE SEGURIDAD
- La señal SIGTERM se envía a un proceso para solicitar su finalización . A diferencia de la señal SIGKILL, el proceso puede captarla e interpretarla o ignorarla. Esto permite que el proceso realice una finalización correcta, liberando recursos y guardando el estado si corresponde. SIGINT es casi idéntico a SIGTERM.
- SIGTSTP
- La señal SIGTSTP se envía a un proceso por medio de su terminal de control para solicitarle que se detenga ( terminal stop ). Generalmente, el usuario la inicia presionando + . A diferencia de SIGSTOP, el proceso puede registrar un controlador de señal para la señal o ignorarla.CtrlZ
- SIGTTIN ySeñal
- Las señales SIGTTIN y SIGTTOU se envían a un proceso cuando intenta leer o escribir respectivamente desde la tty mientras está en segundo plano . Normalmente, estas señales las reciben solo los procesos que están bajo el control de tareas ; los daemons no tienen terminales de control y, por lo tanto, nunca deberían recibir estas señales.
- Trampa de señales
- La señal SIGTRAP se envía a un proceso cuando ocurre una excepción (o trampa ): una condición sobre la que un depurador ha solicitado ser informado, por ejemplo, cuando se ejecuta una función particular o cuando una variable particular cambia de valor.
- Sigurg
- La señal SIGURG se envía a un proceso cuando un socket tiene datos urgentes o fuera de banda disponibles para leer.
- SIGUSR1 ySIGUSR2
- Las señales SIGUSR1 y SIGUSR2 se envían a un proceso para indicar condiciones definidas por el usuario .
- CPU SIGX
- La señal SIGXCPU se envía a un proceso cuando ha utilizado la CPU durante un tiempo que excede un cierto valor predeterminado configurable por el usuario. [21] La llegada de una señal SIGXCPU proporciona al proceso receptor la oportunidad de guardar rápidamente cualquier resultado intermedio y salir sin problemas, antes de que el sistema operativo lo finalice mediante la señal SIGKILL.
- SIGXFSZ
- La señal SIGXFSZ se envía a un proceso cuando crea un archivo que excede el tamaño máximo permitido .
- CABRESTANTE DE SEÑAL
- La señal SIGWINCH se envía a un proceso cuando su terminal de control cambia su tamaño (un cambio de ventana ) . [22]
Señales varias
Las siguientes señales no están especificadas en la especificación POSIX . Sin embargo, a veces se utilizan en varios sistemas.
- SIGEMENTO
- La señal SIGEMT se envía a un proceso cuando se produce una trampa del emulador .
- INFORMACIÓN DE SEGURIDAD
- La señal SIGINFO se envía a un proceso cuando se recibe una solicitud de estado ( información ) del terminal de control.
- SIGPWR
- La señal SIGPWR se envía a un proceso cuando el sistema experimenta un corte de energía .
- SIGLOS
- La señal SIGLOST se envía a un proceso cuando se pierde un bloqueo de archivo .
- Señal de advertencia
- La señal SIGSTKFLT se envía a un proceso cuando el coprocesador experimenta una falla en la pila (es decir , hace estallar la pila cuando está vacía o la empuja cuando está llena). [23] Está definida por Linux, pero no se utiliza en él, donde una falla en la pila del coprocesador x87 generará SIGFPE en su lugar. [24]
- FIRMADO
- La señal SIGUNUSED se envía a un proceso cuando se realiza una llamada al sistema con un número de llamada al sistema no utilizado . Es sinónimo de SIGSYS en la mayoría de las arquitecturas. [23]
- SIGCLD
- La señal SIGCLD es sinónimo de SIGCHLD. [23]
Véase también
Referencias
- ^ McIlroy, MD (1987). Un lector de Unix para investigación: extractos anotados del Manual del programador, 1971–1986 (PDF) (Informe técnico). CSTR. Bell Labs. 139.
- ^ Gagliardi, Pietro. "Programación en C en Plan 9 de Bell Labs". doc.cat-v.org . Consultado el 22 de enero de 2022 .
- ^ "Señales de terminación". La biblioteca C de GNU) .
- ^ "Señales de control de tareas". La biblioteca C de GNU .
- ^ "Señales diversas". La biblioteca C de GNU .
- ^ "Especificaciones básicas de The Open Group, número 6, IEEE Std 1003.1, edición 2004: Interfaces del sistema, capítulo 2". pubs.opengroup.org . Consultado el 20 de diciembre de 2020 .
- ^ "signal(7) - Página del manual de Linux". man7.org . Consultado el 20 de diciembre de 2020 .
- ^ "signal-safety(7) - Página del manual de Linux". man7.org . Consultado el 20 de diciembre de 2020 .
- ^ "Especificaciones básicas de Open Group, número 6, IEEE Std 1003.1, edición 2004: <signal.h>". pubs.opengroup.org . Consultado el 20 de diciembre de 2020 .
- ^ "IEEE Std 1003.1-2017 - kill". IEEE, Open Group.
La correspondencia entre los valores enteros y el valor
sig
utilizado se muestra en la siguiente lista. Los efectos de especificar cualquier
signal_number
distinto de los que se enumeran a continuación no están definidos.
- ^ Michael Kerrisk (25 de julio de 2009). "signal(7)". Manual del programador de Linux (versión 3.22) . Archivos del núcleo de Linux . Consultado el 23 de septiembre de 2009 .
- ^ "perlipc(1)". Guía de referencia para programadores de Perl, versión 5.18 . perldoc.perl.org - Documentación oficial del lenguaje de programación Perl . Consultado el 21 de septiembre de 2013 .
- ^ "Manejo adecuado de SIGINT y SIGQUIT" . Consultado el 6 de octubre de 2012 .
- ^ https://manpages.ubuntu.com/manpages/zesty/man2/kill.2.html Archivado el 28 de enero de 2018 en la sección Wayback Machine NOTAS
- ^ "Proceso de inicio SIGKILL (PID 1)". Desbordamiento de pila .
- ^ "¿Puede el usuario root eliminar el proceso init?". Unix & Linux Stack Exchange .
- ^ "Mac Dev Center: Novedades de Mac OS X: Mac OS X v10.6". 28 de agosto de 2009. Consultado el 18 de noviembre de 2017 .
- ^ "ioctl - controla un dispositivo STREAM". Especificación de llamadas al sistema POSIX . The Open Group . Consultado el 19 de junio de 2015 .
- ^ "¿Qué es una "violación de segmentación"?". support.microfocus.com . Consultado el 22 de noviembre de 2018 .
- ^ "Syscall User Dispatch – La documentación del kernel de Linux". kernel.org . Consultado el 11 de febrero de 2021 .
- ^ "getrlimit, setrlimit - controlan el consumo máximo de recursos". Especificación de llamadas al sistema POSIX . The Open Group . Consultado el 10 de septiembre de 2009 .
- ^ Clausecker, Robert (19 de junio de 2017). "0001151: Introducir la nueva señal SIGWINCH y las funciones tcsetsize(), tcgetsize() para obtener/establecer el tamaño de la ventana de terminal". Austin Group Defect Tracker . Austin Group . Consultado el 12 de octubre de 2017 .
Aceptado como marcado
- ^ abc "signal(7) — Páginas del manual de Linux". manpages.courier-mta.org . Consultado el 22 de noviembre de 2018 .
- ^ "Linux 3.0 x86_64: ¿Cuándo se activa SIGSTKFLT?". Desbordamiento de pila .
- Stevens, W. Richard (1992). Programación avanzada en el entorno UNIX® . Reading, Massachusetts: Addison Wesley. ISBN 0-201-56317-7.
- "Especificaciones básicas de The Open Group, número 7, edición de 2013". The Open Group . Consultado el 19 de junio de 2015 .
Enlaces externos
- Tabla de señales de Unix, Ali Alanjawi, Universidad de Pittsburgh
- Página de manual de Signal de Man7.org
- Introducción a la programación de señales de Unix Introducción a la programación de señales de Unix en Wayback Machine (archivado el 26 de septiembre de 2013)
- Otra introducción a la programación de señales Unix (publicación de blog, 2009)
- Señales UNIX y POSIX fiables por Baris Simsek (almacenado en Internet Archive )
- Manipuladores de señales de Henning Brauer