El proceso de programación del sistema Linux (proceso Linux, función fork (), proceso zombie, proceso huérfano)

1.Proceso Linux

1.1 Concepto de proceso:

  • Desde el punto de vista del usuario: un proceso es un programa en ejecución.
  • Perspectiva del sistema operativo: el sistema operativo ejecuta un programa y necesita describir el proceso de ejecución del programa. Esta descripción se describe mediante una estructura task_struct {}, denominada colectivamente PCB, por lo que para el sistema operativo, el proceso es PCB (proceso bloque de control) pieza de control del programa
  • La información de descripción del proceso incluye: identificador PID, estado del proceso, prioridad, contador de programa, datos de contexto, puntero de memoria, información de estado de E / S e información de contabilidad. Todos necesitan el sistema operativo para la programación.

1.2 Estado del proceso:

/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
static const char * const task_state_array[] = {
    
    
"R (running)", /* 0 */
"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */
"T (stopped)", /* 4 */
"t (tracing stop)", /* 8 */
"X (dead)", /* 16 */
"Z (zombie)", /* 32 */
};

Función 2.fork ()

2.1 Resumen:

El proceso hijo obtenido mediante el uso de la función fork () es una copia del proceso padre. Hereda el espacio de direcciones de todo el proceso del proceso padre:
incluido el contexto del proceso (descripción estática de todo el proceso de las actividades de ejecución del proceso), proceso apilar y abrir archivos Descriptores, configuración de control de señal, prioridad de proceso, número de grupo de proceso, etc. Lo único exclusivo del proceso hijo es su número de proceso, temporizador, etc. (solo una pequeña cantidad de información).

pid_t fork(void);

head Archivo:

#include <sys/types.h>
#include <unistd.h>

Características:

  • Usado para crear un nuevo proceso a partir de un proceso existente, el nuevo proceso se llama proceso hijo y el proceso original se llama proceso padre.

valor de retorno:

  • Éxito: se devuelve 0 en el proceso hijo y el ID del proceso hijo se devuelve en el proceso padre. pid_t es un número entero sin signo.
  • Fallo: devuelve -1.

Ejemplo de código:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
 
int main(int argc, char *argv[])
{
    
    
	pid_t pid;
	pid = fork();
	
	if( pid < 0 ){
    
    	// 没有创建成功
		perror("fork");
	}
	
	if(0 == pid){
    
     // 子进程
		while(1){
    
    
			printf("I am son\n");
			sleep(1);
		}
	}
	else if(pid > 0){
    
     // 父进程
		while(1){
    
    
			printf("I am father\n");
			sleep(1);
		}
	}
	
	return 0;
}

2.2 Resultados de la operación:

Inserte la descripción de la imagen aquí

2.3 Resumen:

  • A través de los resultados de ejecución, puede ver que los procesos padre e hijo hacen una cosa cada uno (cada uno imprime una oración). Aquí, solo vemos que solo hay una pieza de código. De hecho,
    después de fork () , dos espacios de direcciones se ejecutan de forma independiente, lo que es un poco similar a tener dos programas independientes (procesos padre e hijo) ejecutándose. Cabe señalar que en el espacio de direcciones del proceso hijo, el proceso hijo comienza a ejecutar código después de la función fork ().
  • Después de fork (), no está claro si el proceso padre se ejecuta primero o el proceso hijo se ejecuta primero. Esto depende del algoritmo de programación utilizado por el kernel.

3. Proceso zombi

Un proceso usa fork para crear un proceso hijo. Si el proceso hijo sale y el proceso padre no llama a wait () o waitpid () para obtener la información del proceso hijo, el descriptor del proceso hijo todavía se almacena en el sistema, y ​​esto Este tipo de proceso se llama proceso zombi.

Z 进程

3.1 El código simula el proceso zombie:

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

int main()
{
    
    
  printf("输入一遍\n");
  pid_t ret = fork();
  if(ret > 0)
  {
    
    
    //parent    
    while(1)    
    {
    
        
    printf("I am parent! pid is : %d\n", getpid());    
    sleep(1);    
    }    
  }    
  else if(ret == 0)    
  {
    
        
    /child    
    int count = 0;    
    while(count<5)    
    {
    
        
      printf("I am child! pid is : %d, ppid: %d\n", getpid(), getppid());    
      count++;    
      sleep(2);    
    }    
    exit(0);    
  }    
  else    
  {
    
        
    printf("fork error\n");    
  }    
  sleep(1);    
  return 0;    
}

3.2 Visualización de los resultados del proceso zombie:

Inserte la descripción de la imagen aquí

3.3 Daño del proceso zombi:

El estado de salida del proceso hijo siempre se mantendrá, mantener el estado de salida en sí mismo requiere mantenimiento de datos, también pertenece a la información básica del proceso y se almacena en task_structél. Es decir, mientras el estado Z no salga, la PCB siempre debe mantener la información de salida. Si un proceso principal crea muchos procesos secundarios sin reciclaje, lo causará 造成内存资源的极大浪费y lo causará 内存泄露.

4. Proceso huérfano

Cuando el proceso padre sale temprano, el proceso hijo se denomina "proceso huérfano". Una vez que el proceso padre sale, el proceso hijo está en el estado Z cuando quiere salir. Debido a que ningún proceso recibe su información de salida, el proceso de inicio no 1 debe adoptar y reciclar el proceso huérfano para evitar que el proceso hijo se convierta en un proceso zombie.

4.1 El código simula el proceso huérfano:

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

int main()
{
    
    
  pid_t ret = fork();
  if(ret < 0)
  {
    
    
    printf("创建进程失败!\n");
  }
  else if(ret > 0)
  {
    
    
    int count = 0;
    while(count++ < 5)
    {
    
    
      printf("我是父进程(id:%d)\n",getpid());
      sleep(2);
    }
    exit(0);
  }
  else
  {
    
    
    while(1)
    {
    
    
      printf("我是子进程(id:%d)\n",getpid());
      sleep(1);
    }
  }
  sleep(1);
  return 0;
}

4.2 Visualización de los resultados del proceso huérfano:

Inserte la descripción de la imagen aquí

4.3 Resumen:

OS considera esta situación, cuando el proceso padre sale y el proceso hijo todavía se está ejecutando (el proceso hijo se llama proceso huérfano), encuentra un padre para él nuevamente, como se muestra en la figura es el proceso systemd No. 1.

Extensión del proceso No. 1 (init):

Creado por el proceso 0, completa la inicialización del sistema. Es el proceso antepasado de todos los demás procesos de usuario en el sistema.
Todos los procesos en Linux son creados y ejecutados por el proceso init. Primero, se inicia el kernel de Linux, luego se inicia el proceso init en el espacio de usuario y luego se inician otros procesos del sistema. Una vez que se completa el inicio del sistema, init se convertirá en un demonio para monitorear otros procesos en el sistema.

Supongo que te gusta

Origin blog.csdn.net/weixin_45313447/article/details/114443655
Recomendado
Clasificación