GNU/Linux >> Tutoriels Linux >  >> Linux

Fonctionnement du cycle de vie des processus Linux - processus parent, enfant et init

Un processus n'est rien d'autre qu'une instance en cours d'exécution d'un programme. Il se définit également comme un programme en action.

Le concept de processus est le concept fondamental d'un système Linux. Les processus peuvent générer d'autres processus, tuer d'autres processus, communiquer avec d'autres processus et bien plus encore.

Dans ce didacticiel, nous discuterons du cycle de vie d'un processus et aborderons divers aspects qu'un processus traverse au cours de son cycle de vie.

1. Code Vs Programme Vs Processus

Commençons par comprendre la différence entre code, programme et processus.

Code : Voici un exemple de code :

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

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

    return 0;
}

Enregistrons le morceau de code ci-dessus dans un fichier nommé helloWorld.c. Donc ce fichier devient du code.

Programme : Maintenant, lorsque le code est compilé, il produit un fichier exécutable. Voici comment le code ci-dessus est compilé :

$ gcc -Wall helloWorld.c -o helloWorld

Cela produirait un exécutable nommé helloWorld. Cet exécutable est appelé programme.

Processus : Maintenant, lançons cet exécutable :

$ ./helloWorld 

 Hello World

Une fois exécuté, un processus correspondant à cet exécutable (ou programme) est créé. Ce processus exécutera tout le code machine qui était là dans le programme. C'est la raison pour laquelle un processus est appelé instance en cours d'exécution d'un programme.

Pour vérifier les détails du processus nouvellement créé, exécutez la commande ps de la manière suivante :

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

Pour comprendre la sortie de la commande ps, lisez notre article sur les exemples de commande 7 ps.

2. Processus parent et enfant

Chaque processus a un processus parent et il peut avoir ou non des processus enfants. Prenons cela un par un. Considérez la sortie de la commande ps sur ma machine 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

Les nombres entiers dans les deuxième et troisième colonnes de la sortie ci-dessus représentent l'ID de processus et l'ID de processus parent. Observez les chiffres soulignés en gras. Lorsque j'ai exécuté la commande 'ps -aef', un processus a été créé, son ID de processus est 6191. Maintenant, regardez son ID de processus parent, c'est 3079. Si vous regardez vers le début de la sortie, vous verrez cet ID 3079 est l'ID de processus du processus bash. Cela confirme que le shell bash est le parent de toute commande que vous exécutez.

De même, même pour les processus qui ne sont pas créés via le shell, il existe un processus parent. Exécutez simplement la commande 'ps -aef' sur votre machine Linux et observez la colonne PPID (ID de processus parent). Vous ne verrez aucune entrée vide dedans. Cela confirme que chaque processus a un processus parent.

Venons-en maintenant aux processus enfants. Chaque fois qu'un processus crée un autre processus, le premier est appelé parent tandis que le second est appelé processus enfant. Techniquement, un processus enfant est créé en appelant la fonction fork() depuis le code. Habituellement, lorsque vous exécutez une commande à partir du shell, fork() est suivi d'une série de fonctions exec().

Nous avons discuté du fait que chaque processus a un processus parent, cela peut amener une question :qu'adviendra-t-il d'un processus enfant dont le processus parent est tué ? Eh bien, c'est une bonne question, mais revenons-y plus tard.

3. Le processus d'initialisation

Lorsque le système Linux est démarré, la première chose qui est chargée en mémoire est vmlinuz. C'est l'exécutable du noyau Linux compressé. Cela se traduit par la création du processus init. C'est le premier processus créé. Le processus d'initialisation a un PID de un et est le super parent de tous les processus d'une session Linux. Si vous considérez la structure des processus Linux comme un arbre, alors init est le nœud de départ de cet arbre.

Pour confirmer que init est le premier processus, vous pouvez exécuter la commande pstree sur votre machine Linux. Cette commande affiche l'arborescence des processus pour une session Linux.

Voici un exemple de sortie :

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}]
     ...
     ...
     ...

La sortie confirme que init est en haut de l'arborescence des processus. De plus, si vous observez le texte en gras, vous verrez la relation parent-enfant complète du processus pstree. En savoir plus sur pstree dans notre article sur tree et pstree.

Maintenant, revenons à la question (que nous avons laissée ouverte dans la dernière section) sur les conséquences lorsque le processus parent est tué alors que l'enfant est toujours en vie. Et bien dans ce cas, l'enfant devient évidemment orphelin mais est adopté par le processus init. Ainsi, le processus init devient le nouveau parent des processus enfants dont les parents sont terminés.

4. Cycle de vie du processus

Dans cette section, nous discuterons du cycle de vie d'un processus Linux normal avant qu'il ne soit tué et supprimé de la table des processus du noyau.

  • Comme déjà discuté, un nouveau processus est créé via fork() et si un nouvel exécutable doit être exécuté, la famille de fonctions exec() est appelée après fork(). Dès que ce nouveau processus est créé, il est mis en file d'attente dans la file d'attente des processus prêts à être exécutés.
  • Si seul fork() a été appelé, il est fort probable que le nouveau processus s'exécute en mode utilisateur, mais si exec() est appelé, le nouveau processus s'exécutera en mode noyau jusqu'à ce qu'un nouvel espace d'adressage de processus soit créé pour lui.
  • Pendant que le processus est en cours d'exécution, un processus de priorité plus élevée peut le préempter via une interruption. Dans ce cas, le processus préempté passe à nouveau dans la file d'attente des processus prêts à s'exécuter. Ce processus est repris par le planificateur à un stade ultérieur.
  • Un processus peut entrer en mode noyau pendant son exécution. Cela est possible lorsqu'il faut accéder à certaines ressources comme un fichier texte qui est conservé sur le disque dur. Comme les opérations impliquant l'accès au matériel peuvent prendre du temps, il est fort probable que le processus s'endorme et ne se réveille que lorsque les données demandées sont disponibles. Lorsque le processus est réveillé, cela ne signifie pas qu'il commencera à s'exécuter immédiatement, il sera à nouveau mis en file d'attente et sera sélectionné pour exécution par le planificateur au moment approprié.
  • Un processus peut être tué de plusieurs façons. Il peut appeler la fonction exit() pour quitter ou traiter les signaux Linux pour quitter. De plus, certains signaux ne peuvent pas être détectés et entraînent l'arrêt immédiat du processus.
  • Il existe différents types de processus Linux. Une fois le processus tué, il n'est pas complètement éliminé. Une entrée contenant des informations la concernant est conservée dans la table d'adresses du processus du noyau jusqu'à ce que le processus parent appelle explicitement les fonctions wait() ou waitpid() pour obtenir l'état de sortie du processus enfant. Jusqu'à ce que le processus parent le fasse, le processus terminé est appelé processus zombie.

Linux
  1. Comment tuer un processus zombie sous Linux

  2. Comment démarrer la commande Linux en arrière-plan et détacher le processus dans le terminal

  3. Comment installer et configurer Monit sur Linux pour la surveillance des processus

  4. Comment déplacer des fichiers et des répertoires vers le dossier parent sous Linux ?

  5. Linux :Comment savoir où un processus a été démarré et comment il a été démarré ?

Comment afficher les PPID sous Linux

Comment travailler avec le processus de premier plan et d'arrière-plan sous Linux

Comment tuer un processus sous Linux

Comment trouver le PID et le PPID d'un processus sous Linux

Comment tuer les processus sous Linux en utilisant kill, killall et pkill

Comment suivre et tracer un processus Linux