Le concept de processus est fondamental pour comprendre le fonctionnement interne de Linux. Un processus représente l'exécution dynamique d'un programme, gérant les ressources système telles que le processeur (CPU) et la mémoire vive (RAM).
Différence entre Programme et Processus
Un programme est une entité statique : c'est un fichier binaire stocké sur le disque dur. Il ne consomme aucune ressource active tant qu'il n'est pas lancé. À l'inverse, un processus est une instance d'exécution de ce programme. Il est dynamique, possède un identifiant unique (PID) et interagit constamment avec le noyau (kernel) du système.
Multitâche et tranches de temps CPU
Bien qu'un ordinateur donne l'impression de réaliser plusieurs tâches simultanément, un cœur de processeur ne traite qu'une instruction à la fois. Cette illusion de parallélisme est obtenue par le découpage en tranches de temps (time-slicing). L'ordonnanceur (scheduler) du noyau bascule très rapidement d'un processus à l'autre.
Lorsqu'un processus est interrompu pour laisser la place à un autre, le noyau effectue une commutation de contexte (context switch). Il sauvegarde l'état actuel (registres, pointeurs) pour pouvoir reprendre l'exécution exactement là où elle s'était arrêtée.
Hiérarchie et création de processus
Sous Linux, les processus sont organisés de manière arborescente. Tout processus est créé par un parant, à l'exception du premier processus système (systemd ou init).
Il existe trois méthodes principales pour générer un processus :
- fork() : Crée une copie exacte du processus parent. Le fils hérite de l'environnement et des variables, mais possède son propre espace mémoire (via le mécanisme de copie sur écriture).
- exec() : Remplace l'image du processus actuel par un nouveau programme. Contrairement au fork, le processus ne se dédouble pas ; il se transforme.
- clone() : Principalement utilisé pour créer des fils d'exécution (threads) qui partagent certaines ressources (mémoire, descripteurs de fichiers) avec le parent.
// Exemple conceptuel de création de processus
pid_t identifiant = fork();
if (identifiant == 0) {
// Code exécuté par le processus fils
execlp("/bin/ls", "ls", "-l", NULL);
exit(1);
} else if (identifiant > 0) {
// Code exécuté par le parent
wait(NULL); // Attend la fin du fils
printf("Traitement terminé.\n");
}
Les différents états d'un processus
Un processus traverse plusieurs phases durant sa vie :
- Exécution (Running) : Le processus utilise actuellement le processeur ou est prêt à le faire.
- Sommeil interruptible (Sleeping) : Le processus attend un événement (une saisie clavier, une réponse réseau). Il peut être réveillé par un signal.
- Sommeil non-interruptible (Uninteruptible disk sleep) : Souvent lié à des entrées/sorties matérielles (E/S). Le processus ne peut pas être interrompu tant que le matériel n'a pas répondu.
- Zombie : Le processus a terminé son exécution, mais son parent n'a pas encore lu son code de sortie. Il reste une entrée inutile dans la table des processus.
Gestion des tâches (Jobs) et terminaux
Dans un shell, une commande peut être lancée au premier plan (bloquant le terminal) ou en arrière-plan (background). L'ajout du symbole & à la fin d'une commande permet de conserver la main sur le terminal.
# Lancer une compression en arrière-plan
tar -czf archive.tar.gz /data/ &
# Lister les tâches actives du shell
jobs
# Basculer la tâche 1 au premier plan
fg %1
Lorsqu'on ferme un terminal, le signal SIGHUP est envoyé à tous les processus liés. Pour éviter qu'un script ne s'arrête à la déconnexion, on utilise nohup ou des outils comme screen ou tmux.
Signaux et communication inter-processus
Les signaux sont des notifications logicielles envoyées aux processus pour modifier leur comportement.
| Signal | Valeur | Description |
|---|---|---|
| SIGHUP | 1 | Déconnexion du terminal ou rechargement de configuration pour les démons. |
| SIGINT | 2 | Interruption (générée par Ctrl+C). Permet un arrêt propre. |
| SIGKILL | 9 | Arrêt immédiat et forcé. Ne peut être ignoré. |
| SIGTERM | 15 | Demande de terminaison normale (comportement par défaut de kill). |
| SIGCHLD | 17 | Envoyé par un fils à son parent lors de sa terminaison. |
Outils de diagnostic
Pour manipuler les processus, plusieurs utilitaires sont essentiels :
- kill : Envoie un signal à un PID spécifique.
- pkill / killall : Envoient des signaux basés sur le nom du processus ou d'autres critères (utilisateur, terminal).
- lsof : Liste les fichiers ouverts par les processus (très utile pour voir quelle application utilise un port réseau ou un fichier).
- fuser : Identifie les processus qui utilisent un fichier ou un point de montage spécifique.
# Trouver quel processus utilise le port 80
lsof -i :80
# Forcer l'arrêt d'un processus récalcitrant par son nom
pkill -9 nginx
# Vérifier quel processus bloque le démontage d'une clé USB
fuser -v /mnt/usb