Linux: proceso en espera

Proceso en espera

El proceso en espera se refiere al proceso padre esperando que el proceso hijo salga; para obtener el valor de retorno del proceso hijo saliendo; liberando todos los recursos del proceso hijo saliendo; se puede ver que el proceso en espera es muy importante. Como dijimos antes, cuando el proceso hijo sale, si Independientemente del proceso padre, puede convertir el proceso hijo en un proceso zombie y causar pérdidas de memoria. También sabemos que el proceso zombie es muy difícil de manejar. Incluso kill-9 no puede "matarlo", al igual que una persona que se convierte en un zombi. Para nosotros, está muerto y no se puede matar por segunda vez. Y queremos saber cómo se completan las tareas asignadas por el proceso padre al proceso hijo, por ejemplo, el proceso hijo ha terminado de ejecutarse, el resultado es correcto o no, o si sale normalmente. En este punto, podemos recuperar los recursos del proceso hijo y obtener la información de salida del proceso hijo dejando que el proceso padre espere durante el proceso.

Dos métodos de proceso en espera

1.Espere el método`

#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int*status);
返回值:
 成功返回被等待进程pid,失败返回-1。(比如:没有退出子进程)
参数:
 输出型参数,获取子进程退出状态,不关心则可以设置成NULL

wait es una interfaz de bloqueo que maneja el proceso hijo que sale. Por supuesto, si no sale ningún proceso hijo, esperará hasta que haya una salida del proceso hijo antes de llamar al retorno.

Método 2.waitpid

pid_ t waitpid(pid_t pid, int *status, int options);
返回值:
 当正常返回的时候waitpid返回收集到的子进程的进程ID;
 如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
 如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;
参数:
 pid:
 Pid=-1,等待任一个子进程。与wait等效。
 Pid>0.等待其进程ID与pid相等的子进程。
 status:
 WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
 WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)
 options:
 WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进
程的ID。

Nota:
Si el proceso hijo ha salido, cuando se llama a wait / waitpid, wait / waitpid volverá inmediatamente, liberará los recursos y obtendrá la información de salida del proceso hijo.
Si se llama a wait / waitpid en cualquier momento y el proceso hijo existe y se está ejecutando normalmente, es posible que el proceso esté bloqueado.
Si el proceso hijo no existe, se devolverá un error inmediatamente.
Inserte la descripción de la imagen aquí

Comparación de los dos:
1. Esperar espera la salida de cualquier proceso hijo (esperar es un proceso padre, asumiendo que no hay muchos procesos hijos, cualquiera sale, llamará y volverá después del procesamiento)
2. Waitpid puede esperar el proceso hijo especificado, o Esperar cualquier proceso hijo, determinado por el primer parámetro (el primer parámetro pid == -1 significa esperar cualquier proceso)
3.wait es una interfaz de bloqueo (si no sale ningún proceso hijo, esperará
para siempre ) 4.waitpid Puede ser bloqueado por defecto o sin bloqueo. Está determinado por el tercer parámetro (opción == 0 significa bloqueo por defecto) opción == WNOHANG significa sin bloqueo.
Nota: Las operaciones sin bloqueo generalmente requieren operaciones cíclicas . Debe juzgar si se puede procesar hasta que sea responsable de posibles procesos zombies hasta que tenga éxito.
Por ejemplo

   #include <stdio.h>
   #include <stdlib.h>
   #include <unistd.h>
   #include <sys/wait.h>
  
   int main(int argc,char *argv[])
     {
    
    
       pid_t pid = fork();
       if(pid == 0)
      {
    
    
        sleep(5);
        exit(0);
     }
      else if(pid > 0)
      {
    
    
        int ret = waitpid(pid,NULL,WNOHANG);
        if(0 == ret)
        {
    
    
          printf("没有子进程退出!\n");                                          
        }
        while(1)
        {
    
    
          printf("正在打麻将!\n");
        }
     }
      return 0;
    }

Ejecute este programa en este momento y use el comando ps aux | grep para verificar que el proceso hijo se haya convertido en un proceso zombie
Inserte la descripción de la imagen aquí

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
 
int main(int argc, char *argv[])                                                                                                                            
{
    
    
   pid_t pid = fork();
   if(0 == pid)
   {
    
    
     sleep(5);
     exit(0);
   }
   else if(pid > 0)
   {
    
    
     int status;
     while(waitpid(pid,&status,WNOHANG)== 0){
    
    
       printf("没有子进程退出,再等等!");
       sleep(1);
     }
     while(1)
     {
    
    
       printf("正在打麻将!\n");
       sleep(1);
     }
   }
   return 0;
 }

Este problema se resuelve después de usar el procesamiento de bucle.
Inserte la descripción de la imagen aquí

Obtener el estado del proceso secundario

Ya sea wait o waitpid, hay un parámetro de estado. Este parámetro es un parámetro de salida, que es llenado por el sistema operativo. Si se pasa NULL, significa que no se tiene en cuenta el estado de retiro del proceso hijo. De lo contrario, el sistema operativo cambiará el proceso hijo de acuerdo con este parámetro La información de salida del proceso se retroalimenta al proceso padre. El estado no puede tratarse simplemente como una forma plástica, sino como un mapa de bits. Los detalles son los siguientes (solo se estudian los 16 bits bajos de estado
):
Inserte la descripción de la imagen aquí

En lo anterior, tenemos dos escenarios hasta que un proceso sale: salida normal y salida anormal.
Cuando un proceso sale normalmente, el valor de retorno es significativo; de lo contrario, el valor de retorno no tiene sentido. Por lo tanto, antes de obtener el valor de retorno, primero debe pasar los 7 bits inferiores para determinar si el proceso sale normalmente (salida normal, la señal de salida anormal es 0; de lo contrario, es mayor que 0),
Inserte la descripción de la imagen aquí
por lo que el método para determinar si un El proceso sale normalmente es: saque el 7 Bit inferior

status & 0x7f == 0 正常退出
0x7f == 0111 1111

Luego saque los ocho bits altos de los 16 bits bajos

(status >> 8) & 0xff

Este es el estado que queremos obtener.
Código:

#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main( void )
{
    
    
 	pid_t pid;
 	if ( (pid=fork()) == -1 )
 	perror("fork"),exit(1);
	if ( pid == 0 ){
    
    
	sleep(20);
	exit(10);
 } else 
 {
    
    
 	int st;
 	int ret = wait(&st);
 
 	if ( ret > 0 && ( st & 0X7F ) == 0 ){
    
     // 正常退出
	 printf("child exit code:%d\n", (st>>8)&0XFF);
 } else if( ret > 0 ) {
    
     // 异常退出
	 printf("sig code : %d\n", st&0X7F );
	 }
 	}
}

Resultado de la operación: el
Inserte la descripción de la imagen aquí
resultado anterior se ejecuta dos veces, y luego se comparan los resultados de matar el proceso en otros extremos intermedios. Lo anterior es el resultado de la operación de eliminación y el resultado de la parte inferior es el resultado de la operación de eliminación. Si es 9 No .comando, entonces el resultado es el código sig: 9

Supongo que te gusta

Origin blog.csdn.net/qq_43825377/article/details/113826404
Recomendado
Clasificación