GNU/Linux >> Tutoriales Linux >  >> Linux

Cómo funciona el ciclo de vida del proceso de Linux:proceso principal, secundario e inicial

Un proceso no es más que una instancia en ejecución de un programa. También se define como un programa en acción.

El concepto de proceso es un concepto fundamental de un sistema Linux. Los procesos pueden generar otros procesos, eliminar otros procesos, comunicarse con otros procesos y mucho más.

En este tutorial, analizaremos el ciclo de vida de un proceso y nos basaremos en varios aspectos por los que pasa un proceso en su ciclo de vida.

1. Código Vs Programa Vs Proceso

Primero entendamos la diferencia entre código, programa y proceso.

Código: El siguiente es un ejemplo de código:

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

int main(void)
{
    printf("\n Hello World\n");
    sleep(10);

    return 0;
}

Guardemos el código anterior en un archivo llamado helloWorld.c. Entonces este archivo se convierte en código.

Programa: Ahora, cuando se compila el código, produce un archivo ejecutable. Así es como se compila el código anterior:

$ gcc -Wall helloWorld.c -o helloWorld

Esto produciría un ejecutable llamado helloWorld. Este ejecutable se conoce como programa.

Proceso: Ahora, ejecutemos este ejecutable:

$ ./helloWorld 

 Hello World

Una vez ejecutado, se crea un proceso correspondiente a este ejecutable (o programa). Este proceso ejecutará todo el código de máquina que había en el programa. Esta es la razón por la que un proceso se conoce como instancia en ejecución de un programa.

Para verificar los detalles del proceso recién creado, ejecute el comando ps de la siguiente manera:

$ ps -aef | grep hello*
1000      6163  3017  0 18:15 pts/0    00:00:00 ./helloWorld

Para comprender la salida del comando ps, lea nuestro artículo sobre ejemplos de comandos 7 ps.

2. Proceso padre e hijo

Cada proceso tiene un proceso principal y puede o no tener procesos secundarios. Tomemos esto uno por uno. Considere la salida del comando ps en mi máquina Ubuntu:

1000      3008     1  0 12:50 ?        00:00:23 gnome-terminal
1000      3016  3008  0 12:50 ?        00:00:00 gnome-pty-helper
1000      3017  3008  0 12:50 pts/0    00:00:00 bash
1000      3079  3008  0 12:58 pts/1    00:00:00 bash
1000      3321     1  0 14:29 ?        00:00:12 gedit
root      5143     2  0 17:20 ?        00:00:04 [kworker/1:1]
root      5600     2  0 17:39 ?        00:00:00 [migration/1]
root      5642     2  0 17:39 ?        00:00:00 [kworker/u:69]
root      5643     2  0 17:39 ?        00:00:00 [kworker/u:70]
root      5677     2  0 17:39 ?        00:00:00 [kworker/0:2]
root      5680     2  0 17:39 ?        00:00:00 [hci0]
root      5956   916  0 17:39 ?        00:00:00 /sbin/dhclient -d -sf /usr/lib/NetworkManager/nm-dhcp-client.action -pf /run/sendsigs.
root      6181     2  0 18:35 ?        00:00:00 [kworker/1:0]
root      6190     2  0 18:40 ?        00:00:00 [kworker/1:2]
1000      6191  3079  0 18:43 pts/1    00:00:00 ps -aef

Los números enteros en la segunda y tercera columna de la salida anterior representan el ID del proceso y el ID del proceso principal. Observe las cifras resaltadas en negrita. Cuando ejecuté el comando 'ps -aef', se creó un proceso, su ID de proceso es 6191. Ahora, mire su ID de proceso principal, es 3079. Si mira hacia el comienzo de la salida, verá que ID 3079 es el ID de proceso del proceso bash. Esto confirma que bash shell es el padre de cualquier comando que ejecute a través de él.

De manera similar, incluso para los procesos que no se crean a través del shell, existe algún proceso principal. Simplemente ejecute el comando 'ps -aef' en su máquina Linux y observe la columna PPID (ID del proceso principal). No verá ninguna entrada vacía en él. Esto confirma que cada proceso tiene un proceso principal.

Ahora, pasemos a los procesos secundarios. Cada vez que un proceso crea otro proceso, el primero se llama padre, mientras que el segundo se llama proceso hijo. Técnicamente, un proceso secundario se crea llamando a la función fork() desde dentro del código. Por lo general, cuando ejecuta un comando desde el shell, el fork() es seguido por la serie de funciones exec().

Discutimos que cada proceso tiene un proceso principal, esto puede generar una pregunta de qué sucederá con un proceso secundario cuyo proceso principal se elimine. Bueno, esta es una buena pregunta, pero volvamos a ella más tarde.

3. El proceso de inicio

Cuando se inicia el sistema Linux, lo primero que se carga en la memoria es vmlinuz. Es el ejecutable comprimido del kernel de Linux. Esto da como resultado la creación del proceso init. Este es el primer proceso que se crea. El proceso de inicio tiene un PID de uno y es el padre principal de todos los procesos en una sesión de Linux. Si considera la estructura del proceso de Linux como un árbol, init es el nodo inicial de ese árbol.

Para confirmar que init es el primer proceso, puede ejecutar el comando pstree en su caja de Linux. Este comando muestra el árbol de procesos para una sesión de Linux.

Aquí hay una salida de muestra:

init-+-NetworkManager-+-dhclient
     |                |-dnsmasq
     |                `-3*[{NetworkManager}]
     |-accounts-daemon---2*[{accounts-daemon}]
     |-acpid
     |-at-spi-bus-laun-+-dbus-daemon
     |                 `-3*[{at-spi-bus-laun}]
     |-at-spi2-registr---{at-spi2-registr}
     |-avahi-daemon---avahi-daemon
     |-bamfdaemon---3*[{bamfdaemon}]
     |-bluetoothd
     |-colord---{colord}
     |-console-kit-dae---64*[{console-kit-dae}]
     |-cron
     |-cups-browsed
     |-cupsd
     |-2*[dbus-daemon]
     |-dbus-launch
     |-dconf-service---2*[{dconf-service}]
     |-evince---3*[{evince}]
     |-evinced---{evinced}
     |-evolution-sourc---2*[{evolution-sourc}]
     |-firefox-+-plugin-containe---16*[{plugin-containe}]
     |         `-36*[{firefox}]
     |-gconfd-2
     |-gedit---3*[{gedit}]
     |-6*[getty]
     |-gnome-keyring-d---7*[{gnome-keyring-d}]
     |-gnome-terminal-+-bash
     |                |-bash-+-less
     |                |      `-pstree
     |                |-gnome-pty-helpe
     |                `-3*[{gnome-terminal}]
     |-gvfs-afc-volume---2*[{gvfs-afc-volume}]
     |-gvfs-gphoto2-vo---{gvfs-gphoto2-vo}
     |-gvfs-mtp-volume---{gvfs-mtp-volume}
     |-gvfs-udisks2-vo---{gvfs-udisks2-vo}
     |-gvfsd---{gvfsd}
     |-gvfsd-burn---2*[{gvfsd-burn}]
     |-gvfsd-fuse---4*[{gvfsd-fuse}]
     ...
     ...
     ...

El resultado confirma que init está en la parte superior del árbol de procesos. Además, si observa el texto en negrita, verá la relación padre-hijo completa del proceso pstree. Lea más sobre pstree en nuestro artículo sobre tree y pstree.

Ahora, volvamos a la pregunta (que dejamos abierta en la última sección) sobre las consecuencias cuando el proceso padre muere mientras el hijo todavía está vivo. Bueno, en este caso, el niño obviamente queda huérfano pero es adoptado por el proceso init. Por lo tanto, el proceso de inicio se convierte en el nuevo padre de los procesos secundarios cuyos padres han terminado.

4. Ciclo de vida del proceso

En esta sección, discutiremos el ciclo de vida de un proceso normal de Linux antes de que se elimine y se elimine de la tabla de procesos del kernel.

  • Como ya se mencionó, se crea un nuevo proceso a través de fork() y si se va a ejecutar un nuevo ejecutable, se llama a la familia de funciones exec() después de fork(). Tan pronto como se crea este nuevo proceso, se pone en cola en la cola de procesos que están listos para ejecutarse.
  • Si solo se llamó a fork(), es muy probable que el nuevo proceso se ejecute en modo de usuario, pero si se llama a exec(), el nuevo proceso se ejecutará en modo kernel hasta que se cree un nuevo espacio de direcciones de proceso para él.
  • Mientras el proceso se está ejecutando, un proceso de mayor prioridad puede apropiarse de él a través de una interrupción. En este caso, el proceso reemplazado vuelve a entrar en la cola de procesos que están listos para ejecutarse. Este proceso es recogido por el planificador en una etapa posterior.
  • Un proceso puede entrar en modo kernel mientras se ejecuta. Esto es posible cuando requiere acceder a algún recurso como un archivo de texto que se guarda en el disco duro. Dado que las operaciones que implican el acceso al hardware pueden llevar tiempo, es muy probable que el proceso entre en suspensión y se active solo cuando los datos solicitados estén disponibles. Cuando el proceso se activa, no significa que comenzará a ejecutarse de inmediato, volverá a ponerse en cola y el programador lo seleccionará para su ejecución en el momento adecuado.
  • Un proceso se puede matar de muchas maneras. Puede llamar a la función exit() para salir o puede procesar señales de Linux para salir. Además, algunas señales no se pueden captar y hacen que el proceso finalice inmediatamente.
  • Hay diferentes tipos de procesos de Linux. Una vez que se mata el proceso, no se elimina por completo. Una entrada que contiene alguna información relacionada con ella se mantiene en la tabla de direcciones del proceso Kernel hasta que el proceso principal llama explícitamente a las funciones wait() o waitpid() para obtener el estado de salida del proceso secundario. Hasta que el proceso principal haga esto, el proceso terminado se conoce como proceso zombi.

Linux
  1. Cómo iniciar el comando de Linux en segundo plano y separar el proceso en la terminal

  2. Cómo instalar vtop en Linux

  3. Linux:¿un proceso de "subsegador"?

  4. ¿Cómo hacer que el proceso hijo muera después de que el padre salga?

  5. ¿Cómo muevo archivos y directorios a la carpeta principal en Linux?

Cómo mostrar PPID en Linux

Cómo trabajar con procesos en primer plano y en segundo plano en Linux

Cómo MATAR un proceso en Linux

Cómo encontrar el PID y PPID de un proceso en Linux

Cómo matar procesos en Linux usando kill, killall y pkill

Cómo rastrear y rastrear un proceso de Linux