Volver al temario
Tema 04 · 70 páginas

Comunicación y sincronización

Tema completo Modo estudio
GUÍA DE ESTUDIO · Páginas 3645 Ver PDF

3.2.2. Linux: señales POSIX

Material de estudio basado en la edición de 2014. Borrador pendiente de revisión editorial independiente.

Linux: Señales POSIX

Resumen

La interfaz POSIX de señales (también llamada reliable signals) es la más completa y robusta. Es la utilizada por Linux.

Terminología

TérminoDefinición
GeneraciónMomento en que se produce la señal
TratamientoRutina de atención para una señal (defecto del SO o usuario)
DepósitoMomento en que se empieza a ejecutar la rutina de tratamiento
Señal pendienteSeñal generada pero aún no depositada
ProgramaciónAsociar un tratamiento a una señal
CapturaEjecución de la rutina de usuario para atender la señal
Señal bloqueadaEl SO no deposita señales de este tipo mientras estén bloqueadas
Señal ignoradaEl SO descarta las señales de este tipo

Lista de señales POSIX (principales)

SeñalSignificadoTratamiento por defecto
SIGHUPCorte de línea de comunicaciónEXIT
SIGINTTecla de control (Ctrl-C)EXIT
SIGABRTAbortar ejecuciónEXIT + CORE
SIGFPEExcepción de coma flotanteEXIT + CORE
SIGKILLDestruir proceso (no se puede ignorar/bloquear)EXIT
SIGSEGVAcceso indebido a memoriaEXIT + CORE
SIGPIPEEscritura en pipe sin lectorEXIT
SIGALRMExpiración de temporizadorEXIT
SIGTERMSolicitud de fin de procesoEXIT
SIGUSR1/SIGUSR2Para uso de aplicacionesEXIT
SIGCHLDMuerte de proceso hijoIGNORE
SIGSTOPDetener proceso (Ctrl-Z, no reprogramable)STOP
SIGCONTReanudar proceso detenidoCONT

Conjuntos de señales (sigset_t)

POSIX ofrece un tipo sigset_t y funciones para manipularlo:

int sigemptyset(sigset_t *set);           /* Conjunto vacío */
int sigfillset(sigset_t *set);            /* Todos los signals */
int sigaddset(sigset_t *set, int signum); /* Añadir signal */
int sigdelset(sigset_t *set, int signum); /* Eliminar signal */
int sigismember(const sigset_t *set, int signum); /* ¿Pertenece? */

Programación de señales (sigaction)

struct sigaction {
    void (*sa_handler)(int);  /* Rutina de atención */
    sigset_t sa_mask;         /* Señales bloqueadas durante la rutina */
    int sa_flags;             /* Modificar comportamiento POSIX */
};

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
  • sa_handler: rutina a ejecutar, SIG_IGN para ignorar, SIG_DFL para defecto.
  • sa_mask: señales bloqueadas mientras se ejecuta la rutina de atención.
  • sa_flags = 0 para comportamiento POSIX estándar.
  • La programación es válida hasta que se vuelva a programar la misma señal.
  • En fork, el hijo hereda la programación. En exec, todas recuperan la programación por defecto excepto las marcadas como SIG_IGN.

Generación de señales

int kill(pid_t pid, int sig);              /* Genera señal "inmediatamente" */
unsigned int alarm(unsigned int seconds);   /* Temporizador → SIGALRM */
  • kill: genera una señal sobre un proceso. Error si pertenece a otro usuario o no existe.
  • alarm: programa un temporizador. Al expirar, genera SIGALRM. Con parameter 0, cancela el temporizador.

Conjunto de señales bloqueadas (sigprocmask)

int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
  • SIG_BLOCK: añade señales al conjunto bloqueado.
  • SIG_UNBLOCK: elimina señales del conjunto bloqueado.
  • SIG_SETMASK: asigna directamente el conjunto.

Se hereda en fork y se mantiene en exec. Si se modifica dentro de una rutina de atención, el SO restaura el valor previo al acabar.

Errores frecuentes: usar SIG_SETMASK sin considerar las señales ya bloqueadas. La opción correcta es bloquear temporalmente, usar, y restaurar el valor anterior.

Espera de señales (sigsuspend)

int sigsuspend(const sigset_t *mask);

Realiza atómicamente:

  1. Asigna mask como nuevo conjunto de señales bloqueadas.
  2. Bloquea el proceso hasta que se deposite una señal no bloqueada.

Al depositar la señal, ejecuta el tratamiento, restaura el valor previo del conjunto bloqueado y el proceso continúa.

Problema con pause: puede haber una carrera entre verificar una variable y llamar a pause, perdiéndose la señal. sigsuspend resuelve esto ejecutando las dos operaciones de manera atómica.

Depósito sobre procesos bloqueados

Cuando un proceso está bloqueado (leyendo de pipe vacía, en sem_wait, etc.) y recibe una señal:

  • Si el tratamiento no mata al proceso, el SO puede:
    • Abortar la llamada al sistema (devuelve -1 con errno = EINTR).
    • Reiniciar la llamada al sistema (el proceso se vuelve a bloquear).

Depende del tipo de llamada y de sa_flags. Se recomienda control exhaustivo de errores.

Ideas clave

  • POSIX es la interfaz de señales más completa y fiable para Linux.
  • sigaction permite definir rutinas de atención con máscara de bloqueo temporal.
  • sigprocmask gestiona el conjunto de señales bloqueadas del proceso.
  • sigsuspend resuelve la carrera entre verificación y espera de forma atómica.
  • Las señales en procesos bloqueados pueden abortar o reiniciar la llamada al sistema.
  • No se puede reprogramar SIGKILL ni SIGSTOP.
Consultar el contenido original