# 1. Le noyau et les processus Le noyau (kernel) est la couche unique en mode privilégié qui arbitre l'accès au matériel pour tous les programmes en espace utilisateur. Cette section couvre le cycle de vie d'un processus, l'ordonnanceur, et les deux primitives d'isolation qui fondent toute la conteneurisation moderne : les *namespaces* et les *cgroups*. ## Cycle de vie d'un processus - **`fork()`** duplique le processus appelant (copie-sur-écriture des pages mémoire — aucune copie physique tant qu'aucune des deux copies n'écrit). - **`exec*()`** remplace l'image mémoire du processus courant par un nouveau programme, en conservant le même PID. - **`wait()`/`waitpid()`** : le parent récupère le code de sortie de l'enfant. Un enfant terminé mais non « attendu » devient un **processus zombie** (visible avec l'état `Z` dans `ps`) — il ne consomme plus de mémoire mais garde son entrée dans la table des processus jusqu'à ce que le parent appelle `wait()` ou se termine lui-même. - Un processus dont le parent meurt avant lui est **ré-adopté** par le processus 1 (init/systemd sur un système moderne), qui doit appeler `wait()` en boucle pour éviter l'accumulation de zombies orphelins. ## L'ordonnanceur (scheduler) Le noyau Linux utilise depuis la 6.6 **EEVDF** (Earliest Eligible Virtual Deadline First) comme ordonnanceur par défaut pour les tâches classiques, en remplacement du CFS (Completely Fair Scheduler) historique — objectif : réduire la latence perçue sous forte charge sans sacrifier le débit global. Chaque tâche reçoit une part de temps CPU proportionnelle à sa priorité *nice* (de -20, priorité la plus haute, à +19, la plus basse). Les classes temps réel (`SCHED_FIFO`, `SCHED_RR`) et la classe deadline (`SCHED_DEADLINE`) restent disponibles pour des charges à contrainte temporelle stricte, orthogonales au *nice*. ## Espace noyau vs espace utilisateur Un programme en espace utilisateur ne peut pas accéder directement au matériel : toute opération privilégiée passe par un **appel système** (`syscall`), un point d'entrée contrôlé qui fait basculer le CPU en mode noyau le temps de l'opération. `strace` permet d'observer chaque appel système émis par un processus — outil de diagnostic de premier recours (détaillé en section 9). ## Namespaces — isoler ce qu'un processus « voit » Un namespace restreint la vue qu'un groupe de processus a d'une ressource globale du système, sans dupliquer physiquement cette ressource. Le noyau en expose huit types : - **PID** : un processus dans un namespace PID enfant a son propre PID 1 et ne voit aucun processus hors de son namespace. - **NET** : pile réseau, table de routage et interfaces propres — base de l'isolation réseau des conteneurs. - **MNT** : arborescence de points de montage propre. - **UTS** : nom d'hôte et nom de domaine propres. - **IPC** : files de messages, sémaphores et mémoire partagée System V isolés. - **USER** : correspondance d'UID/GID propre — un processus peut être root (UID 0) *à l'intérieur* du namespace tout en restant un utilisateur non privilégié à l'extérieur, pilier de sécurité des conteneurs sans privilèges (*rootless*). - **CGROUP** : vue propre de la hiérarchie de cgroups (masque l'arborescence complète de l'hôte). - **TIME** (depuis 5.6) : horloges monotone et démarrage propres — utile pour migrer un conteneur sans décaler son uptime apparent. ## cgroups v2 — limiter et compter ce qu'un groupe de processus consomme Les *control groups* organisent les processus en une hiérarchie **unique** (depuis la v2, qui a remplacé la hiérarchie multiple et incohérente de la v1) montée sur `/sys/fs/cgroup`. Chaque nœud de la hiérarchie porte des fichiers de contrôle standardisés : - `cpu.max` : quota CPU (période + plafond). - `memory.max` / `memory.high` : plafond dur et seuil de ralentissement progressif avant plafond. - `io.max` : débit maximal par périphérique bloc. - `pids.max` : nombre maximal de processus/threads dans le groupe — protège contre une fork-bomb au niveau du groupe, pas seulement du système entier. systemd monte et gère cette hiérarchie de façon transparente pour chaque service (voir section 2) : chaque unité `.service` obtient son propre sous-groupe cgroup, visible avec `systemd-cgls`. *(Schéma disponible : `schema.svg`, dans ce dossier.)*