Señal (notas de estudio)

1. ¿Qué es una señal?

1.1 Resumen de señales

     Una señal es un evento generado por los sistemas UNIX y Linux en respuesta a ciertas condiciones, y el proceso que recibe la señal realiza alguna acción en consecuencia. La señal es una interrupción suave, que es una simulación del mecanismo de interrupción a nivel de software. .

Las señales pueden hacer que un proceso en ejecución sea interrumpido por otro proceso asíncrono en ejecución para manejar un evento inesperado.

1.2 Signal es un método de comunicación asíncrono

        El proceso no tiene que esperar a que llegue la señal, y el proceso no sabe cuándo llega la señal.
La señal puede interactuar directamente entre el proceso del espacio del usuario y el proceso del espacio del kernel, y el proceso del kernel puede usarla para notificar al proceso del espacio del usuario qué eventos del sistema han ocurrido.

1.3 Características de la señal

El nombre de cada señal comienza con los caracteres SIG.
Cada señal corresponde a un código digital, y en el archivo de encabezado signum.h, estas señales se definen como números enteros positivos.

Ruta de definición del nombre de la señal:
             /usr/include/i386-linux-gnu/bits/signum.h
En Linux, para ver la correspondencia entre estas señales y códigos, puede usar el comando: kill -l

 1.4 Las teclas de acceso directo generan señales

1. Cuando el usuario presione ciertas teclas del terminal, se generará una señal.
Por ejemplo:
presionar la combinación de teclas "Ctrl+c" en el terminal generalmente genera la señal de interrupción SIGINT, presionar la tecla "Ctrl+\" en el terminal generalmente genera la señal de interrupción SIGQUIT y presionar la tecla "Ctrl+z" en el terminal generalmente genera la señal de interrupción SIGSTOP.
2. Una excepción de hardware generará una señal.
Divisor por 0, acceso a memoria inválido, etc. Estas condiciones generalmente son detectadas por el hardware y notificadas al kernel, que luego genera las señales apropiadas para los procesos correspondientes.
3. La anomalía del software generará una señal.
Se genera una señal cuando se detecta que se ha producido una condición de software y se notifica al proceso al respecto. (Por ejemplo, un proceso padre-hijo enviará automáticamente una señal SIGCHLD cuando el proceso hijo se suspenda o se cierre)

Dos, función de señal de señal

Archivo principal:

                 #incluir <señal.h>

función:

                typedef void (*sighandler_t)(int);
                sighandler_t signal(int signum,sighhandler_t handler);
Función:
                 Registre la función de procesamiento de señales, es decir, determine la dirección de entrada de la función de procesamiento después de recibir la señal.
Parámetros: signum: valor del controlador
                de número de señal :                               ignorar la señal: SIG_IGN                               ejecuta la acción predeterminada del sistema: SIG_DFL                                función de procesamiento de señal personalizada: nombre de la función de procesamiento de señal Valor devuelto:                éxito: devuelve la dirección de la función, que se registró por última vez para esta señal La dirección de la función de manejo de señales.                  Fallo: devolver SIG_ERR
               






 

Nota: Las dos señales SIGKILL y SIGSTOP no se pueden ignorar ni capturar

2.1 Función resumen

                      señal sighandler_t( int signum,   manejador sighandler_t );

Esta función no es difícil de encontrar, el primer parámetro se establece en una de las señales bajo kill -l (excepto SIGKILL, SIGSTOP )

Para el segundo parámetro, hay tres opciones:

El primero se establece en SIG_IGN.  La señal del primer parámetro se ignora
y la segunda configuración es SIG_DFL.   Ejecute la acción del primer parámetro                            
y la tercera configuración es el nombre de la función de procesamiento de señal  , procesamiento de señal personalizado

3. Caso de uso de la función de señal

3.1, la señal está configurada para ignorar el modo

#include<stdio.h>
#include<signal.h>
#include<stdlib.h>
#include<unistd.h>

int main()
{
	
	if(signal(SIGINT,SIG_IGN)==SIG_ERR)
  {
	  
	   perror("fail to signal : sigint");
	   exit(1);
	    
	    }
	
	if(signal(SIGQUIT,SIG_IGN)==SIG_ERR)
	{
		
		perror("fail to signnal : singquit");
		exit(1);
		}
    	
	  while(1)
	  {
		  printf("Hello world\n");
		  sleep(1);
		    
			}
	
	 return 0;
	
	 }

Este código está configurado para presionar la tecla "Ctrl+\" o "Ctrl+c" para enviar una señal en el terminal, se ignorará, es decir, no se pausará ni saldrá.

resultado de la operación

 

3,2, la señal se establece como el modo predeterminado

#include<stdio.h>
#include<signal.h>
#include<stdlib.h>
#include<unistd.h>

int main()
{
	
	if(signal(SIGINT,SIG_DFL)==SIG_ERR)
  {
	  
	   perror("fail to signal : sigint");
	   exit(1);
	    
	    }

	
	
	if(signal(SIGQUIT,SIG_DFL)==SIG_ERR)
	{
			
		perror("fail to signnal : singquit");
		exit(1);
		
		}
    	
	  while(1)
	  {
		  printf("Hello world\n");
		  sleep(1);
		    
			}
	
	
	
	 return 0;
	
	 }

Este código está configurado para presionar la tecla "Ctrl+\" o "Ctrl+c" para enviar una señal en el terminal, y la ejecución finalizará o saldrá de forma predeterminada.

resultado de la operación

3.3, la señal está configurada para procesamiento de señal personalizado

#include<stdio.h>
#include<signal.h>
#include<stdlib.h>
#include<unistd.h>

void hander(int sig);


int main()
{
	
	if(signal(SIGINT,hander)==SIG_ERR)
  {
	  
	   perror("fail to signal : sigint");
	   exit(1);
	    
	    }

	
	
	if(signal(SIGQUIT,hander)==SIG_ERR)
	{
			
		perror("fail to signnal : singquit");
		exit(1);
		
		}
    	
	  while(1)
	  {
		  printf("Hello world\n");
		  sleep(1);
		    
			}

   
       return 0;
}

	void hander(int sig)
 {
       if(sig == SIGINT)
	 {
	    printf("SIGINT正在处理\n");
	  }
		
	    if(sig == SIGQUIT)
	 {
		 printf("SIGQUIT正在处理\n");
	
	  }
	
	 }

Este código solo captura la señal, y ejecuta el contenido del segundo parámetro a través de la señal capturada; pero no terminará ni saldrá

resultado de la operación

 

4. Expansión: proceso padre-hijo, use la función de señal de señal para recuperar los recursos del proceso hijo ( énfasis )

 4.1 Concepto de SIGCHLD

        Ya sea que un proceso termine normal o anormalmente, el núcleo del sistema envía una señal SIGCHLD (17) a su proceso principal. El proceso principal puede reclamar de forma asíncrona los recursos del proceso secundario ( es decir, el proceso zombi ) en la función de procesamiento de señales para la señal SIGCHLD (17) , que es concisa y eficiente.

4.2, que es un proceso zombie

El proceso secundario salió por sí mismo y el proceso principal no llamó a la función wait o waitpid para limpiar el estado del proceso secundario, por lo que este estado siempre existirá en la lista de procesos.

4.3 Dos formas comunes de resolver procesos zombie

    1. El proceso principal debe llamar a la función wait/waitpid para recuperar los recursos del proceso secundario.

    2. Use la función de señal de señal para recuperar los recursos del proceso secundario

5. Caso: use la función de señal de señal para reciclar el proceso secundario (es decir, el proceso zombie)

5.1 Ejemplo de un proceso zombie (sin usar la función de señal de señal)

#include<stdio.h>
#include<signal.h>
#include<stdlib.h>
#include<unistd.h>

int main()
{
	pid_t pid;

    pid= fork();
  if(pid < 0)
  {
	  perror("create fork fail ");
	  exit(1);
	  } 
	   
      if(pid==0)
	 {
		 while(1)
		{
		   static int i=0;
			 i++;
		 printf("this is son : pid =%d\n",getpid());	 
		     sleep(1);
			 if(i==3)
			 {
				 exit(1);
				 }
			 }
		 
		 }
		 
	 else if(pid>0)
	 {
		 while(1)
		 {
	      printf("Hello this is father: pid =%d\n",getpid());
		  sleep(1);
		 }
	 }	  
	    		   
       return 0;
}

Ejecución de resultados ( el cuadro rojo Z+ en la siguiente figura indica un proceso zombi )

 5.2 Use la función de señal de señal para reciclar el proceso zombie

#include<stdio.h>
#include<signal.h>
#include<stdlib.h>
#include<unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
 
void handler(int sig)
{
	wait(NULL);
	
	}
 
int main()
{
	pid_t pid;

    pid= fork();

	signal(SIGCHLD,handler);

  if(pid < 0)
  {
	  perror("create fork fail ");
	  exit(1);
	  } 
	   
      if(pid==0)
	 {
		 while(1)
		{
		   static int i=0;
			 i++;
		 printf("this is son : pid =%d\n",getpid());	 
		     sleep(1);
			 if(i==3)
			 {
				 exit(1);
				 }
		     }		 
		 }
		 
	 else if(pid>0)
	 {
		 while(1)
		 {
	      printf("Hello this is father: pid =%d\n",getpid());

		  sleep(1);
		 }
	 }	  
	   	   
       return 0;
}


El resultado de la operación (el cuadro rojo se convierte en un S+ normal) significa que el reciclaje se ha realizado correctamente

 

 

Supongo que te gusta

Origin blog.csdn.net/weixin_47783699/article/details/128002312
Recomendado
Clasificación