in

Señales en lenguaje C – GeeksforGeeks

gfg 200x200 min


Prerequisite : Fork system call, Wait system call
A signal is a software generated interrupt that is sent to a process by the OS because of when user press ctrl-c or another process tell something to this process.
There are fix set of signals that can be sent to a process. signal are identified by integers.
Signal number have symbolic names. For example SIGCHLD is number of the signal sent to the parent process when child terminates.
Examples:

#define SIGHUP  1   /* Hangup the process */ 
#define SIGINT  2   /* Interrupt the process */ 
#define SIGQUIT 3   /* Quit the process */ 
#define SIGILL  4   /* Illegal instruction. */ 
#define SIGTRAP 5   /* Trace trap. */ 
#define SIGABRT 6   /* Abort. */

OS Structures for Signals

  • For each process, the operating system maintains 2 integers with the bits corresponding to a signal numbers.
  • The two integers keep track of: pending signals and blocked signals
  • With 32 bit integers, up to 32 different signals can be represented.

Example :
In the example below, the SIGINT ( = 2) signal is blocked and no signals are pending.
arra3

A signal is sent to a process setting the corresponding bit in the pending signals integer for the process. Each time the OS selects a process to be run on a processor, the pending and blocked integers are checked. If no signals are pending, the process is restarted normally and continues executing at its next instruction.

If 1 or more signals are pending, but each one is blocked, the process is also restarted normally but with the signals still marked as pending. If 1 or more signals are pending and NOT blocked, the OS executes the routines in the process’s code to handle the signals.

Default Signal Handlers

There are several default signal handler routines. Each signal is associated with one of these default handler routine. The different default handler routines typically have one of the following actions:

  • Ign: Ignore the signal; i.e., do nothing, just return
  • Term: terminate the process
  • Cont: unblock a stopped process
  • Stop: block the process

#include<stdio.h>

#include<signal.h>

 

int main()

{

    signal(SIGINT, handle_sigint);

    while (1)

    {

        printf(“hello worldn”);

        sleep(1);

    }

    return 0;

}

Salida: Imprime hola mundo infinitas veces. Si el usuario presiona ctrl-c para terminar el proceso debido a SIGINT señal enviada y su controlador predeterminado para terminar el proceso.

hello world   
hello world         
hello world         
terminated          

Controladores de señales definidos por el usuario

Un proceso puede reemplazar el manejador de señales predeterminado para casi todas las señales (pero no SIGKILL) por su propia función de manejador del usuario.
Una función de manejador de señales puede tener cualquier nombre, pero debe tener el tipo de retorno void y tener un parámetro int.
Ejemplo: puede elegir el nombre sigchld_handler para un manejador de señales para el SIGCHLD señal (terminación de un proceso hijo). Entonces la declaración sería:

void sigchld_handler(int sig);

Cuando se ejecuta un manejador de señales, el parámetro que se le pasa es el número de la señal. Un programador puede usar la misma función de manejador de señales para manejar varias señales. En este caso, el manejador necesitaría verificar el parámetro para ver qué señal se envió. Por otro lado, si una función de manejo de señales solo maneja una señal, no es necesario molestarse en examinar el parámetro, ya que siempre será ese número de señal.

#include<stdio.h>

#include<signal.h>

 

void handle_sigint(int sig)

{

    printf("Caught signal %dn", sig);

}

 

int main()

{

    signal(SIGINT, handle_sigint);

    while (1) ;

    return 0;

}

Producción:

^CCaught signal 2  // when user presses ctrl-c
^CCaught signal 2 

Envío de señales a través de kill ()

Podemos enviar una señal usando kill () al proceso.

int kill(pid_t pid, int signal);
pid: id of destination process
signal: the type of signal to send
Return value: 0 if signal was sent successfully

Ejemplo:

pid_t iPid = getpid(); /* Process gets its id.*/
kill(iPid, SIGINT);  /* Process sends itself a  SIGINT signal   
(commits suicide?)(because of SIGINT 
signal default handler is terminate the process) */
        

Preguntas

1. ¿Cuál es el resultado del siguiente programa?

#include<stdio.h>

#include<wait.h>

#include<signal.h>

int main()

{

    int stat;

    pid_t pid;

    if ((pid = fork()) == 0)

        while(1) ;

    else

    {

        kill(pid, SIGINT);

        wait(&stat);

        if (WIFSIGNALED(stat))

            psignal(WTERMSIG(stat), "Child term due to");

    }

}

Producción:

 Child term due to: Interrupt

2. ¿Cuál es el resultado del siguiente programa?

#include<stdio.h>

#include<signal.h>

#include<wait.h>

int val = 10;

void handler(int sig)

{

    val += 5;

}

int main()

{

    pid_t pid;

    signal(SIGCHLD, handler);

    if ((pid = fork()) == 0)

    {

        val -= 3;

        exit(0);

    }

    waitpid(pid, NULL, 0);

    printf("val = %dn", val);

    exit(0);

}

Producción:

val = 15 

3. Considere el siguiente código. ¿Cuál es la salida?

#include<stdio.h>

#include<wait.h>

#include<signal.h>

pid_t pid;

int counter = 0;

void handler1(int sig)

{

    counter++;

    printf("counter = %dn", counter);

    

    fflush(stdout);

    kill(pid, SIGUSR1);

}

void handler2(int sig)

{

    counter += 3;

    printf("counter = %dn", counter);

    exit(0);

}

 

int main()

{

    pid_t p;

    int status;

    signal(SIGUSR1, handler1);

    if ((pid = fork()) == 0)

    {

        signal(SIGUSR1, handler2);

        kill(getppid(), SIGUSR1);

        while(1) ;

    }

    if ((p = wait(&status)) > 0)

    {

        counter += 4;

        printf("counter = %dn", counter);

    }

}

Producción

counter = 1         //(parent’s handler) 
counter = 3         //(child’s handler) 
counter = 5         //(parent’s main) 

Este artículo es una contribución de Kadam Patel. Si te gusta GeeksforGeeks y te gustaría contribuir, también puedes escribir un artículo usando contrib.geeksforgeeks.org o envíe su artículo por correo electrónico a contrib@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks.

Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema discutido anteriormente.

Si desea aprender de los mejores videos seleccionados y problemas de práctica, consulte el Curso básico de C de Básico a Avanzado C.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

apple touch icon@2

¿Cómo puedo dividir y analizar una cadena en Python?

edit

Cable vs DSL: diferencia y comparación