Cómo usar sigsuspend

Tengo este código, y tengo que hacer que el bloque del progtwig espere repetidamente una señal. Mi maestro quiere que usemos sigsuspend y máscaras en lugar de hacer una pausa o dormir. No estoy familiarizado con el sigsuspend o la máscara, sé que sigsuspend () reemplaza temporalmente la máscara de señal del proceso de llamada con la máscara dada por la máscara y luego suspende el proceso hasta la entrega de una señal cuya acción es invocar un controlador de señal o para terminar un proceso. Pero, ¿cómo lo implemento?

#include  #include  #include  #include  #include  unsigned Conta = 0; void mypause(int sign) { switch (sign) { case SIGINT: printf("You've pressed ctrl-C\n"); printf("I'm running waiting for a signal...\n"); Conta++; break; case SIGQUIT: printf("You've pressd ctrl-\\n"); printf("Number of times you've pressed CTRL-C: %d", Conta); exit(0); break; } } int main() { alarm(3); printf("I'm Alive\n"); signal(SIGINT, mypause); signal(SIGQUIT, mypause); printf("I'm running, waiting for a signal...\n"); while (1) { } return (0); } 

La forma sencilla de comenzar es simplemente llamar a sigsuspend con una máscara vacía (es decir, cualquier señal puede activar el progtwig):

 sigset_t myset; (void) sigemptyset(&myset); while (1) { (void) printf("I'm running, waiting for a signal...\n"); (void) sigsuspend(&myset); } 

El siguiente paso sería usar sigprocmask para deshabilitar las dos señales manejadas ( SIGINT y SIGQUIT ) para que no se produzcan cuando no se espera de ellas en sigsuspend . A continuación, utilizaría la “máscara antigua” obtenida de sigprocmask lugar de la máscara vacía al suspender.

La descripción del manual de GNU libc parece clara y completa:

Función: int sigsuspend (const sigset_t * set)

Esta función reemplaza la máscara de señal del proceso con set y luego suspende el proceso hasta que se entrega una señal cuya acción es terminar el proceso o invocar una función de manejo de señal. En otras palabras, el progtwig se suspende efectivamente hasta que llega una de las señales que no es miembro de un conjunto.

Si el proceso se reactiva mediante la entrega de una señal que invoca una función de manejador, y la función de manejador regresa, entonces sigsuspend también regresa.

La máscara permanece establecida solo mientras sigsuspend esté esperando. La función sigsuspend siempre restaura la máscara de señal anterior cuando regresa.

El valor de retorno y las condiciones de error son las mismas que para la pausa.

Con sigsuspend, puede reemplazar la pausa o el ciclo de sueño en la sección anterior con algo completamente confiable:

  sigset_t mask, oldmask; ... /* Set up the mask of signals to temporarily block. */ sigemptyset (&mask); sigaddset (&mask, SIGUSR1); ... /* Wait for a signal to arrive. */ sigprocmask (SIG_BLOCK, &mask, &oldmask); while (!usr_interrupt) sigsuspend (&oldmask); sigprocmask (SIG_UNBLOCK, &mask, NULL); 

Este último código es un poco complicado. El punto clave a recordar aquí es que cuando sigsuspend regresa, restablece la máscara de señal del proceso al valor original, el valor anterior a la llamada a sigsuspend; en este caso, la señal SIGUSR1 se bloquea nuevamente. La segunda llamada a sigprocmask es necesaria para desbloquear explícitamente esta señal.

Otro punto: puede que se pregunte por qué el bucle while es necesario en absoluto, ya que el progtwig aparentemente solo espera una señal SIGUSR1. La respuesta es que la máscara que se pasa a sigsuspend permite que el proceso se despierte mediante la entrega de otros tipos de señales, también, por ejemplo, señales de control de trabajo. Si el proceso se reactiva con una señal que no establece usr_interrupt, simplemente se suspende nuevamente hasta que finalmente llegue el tipo de señal “correcta”.

Esta técnica requiere algunas líneas más de preparación, pero se necesita solo una vez para cada tipo de criterio de espera que desee utilizar. El código que realmente espera es solo cuatro líneas.