Les processus dans les systèmes d'exploitation de type UNIX (notamment Linux, macOS, BSD, etc.) sont créés et supprimés via une combinaison d'appels système et de mécanismes internes du noyau.
Création de processus :
La principale façon dont un nouveau processus est créé est via l'appel système `fork()`. `fork()` crée une copie presque identique du processus appelant (le processus *parent*). Le processus parent et le processus *enfant* nouvellement créé continuent l'exécution à partir du point de l'appel `fork()`. La principale différence est la valeur de retour de `fork()` :
* Dans le processus parent : `fork()` renvoie l'ID de processus (PID) du processus enfant. Ce PID est un identifiant unique pour l'enfant.
* Dans le processus enfant : `fork()` renvoie 0.
Après `fork()`, les processus parent et enfant suivent généralement des chemins d'exécution différents. Le processus enfant utilise souvent la famille d'appels système `exec()` (`execl`, `execv`, `execvp`, etc.) pour remplacer son image actuelle par un nouveau programme. `exec()` écrase l'espace mémoire de l'enfant avec le code et les données du nouveau programme. Si l'enfant n'utilise pas `exec()`, il continue d'exécuter le même code que le parent, créant ainsi un véritable clone.
D'autres façons dont les processus sont créés incluent :
* `vfork()` (moins courant et potentiellement problématique) : Similaire à `fork()`, mais avec des différences subtiles dans le partage de mémoire. Généralement évité en raison de blocages potentiels.
* `clone()` (plus avancé) : Offre un contrôle plus précis sur les ressources partagées entre les processus parent et enfant. Utilisé dans les bibliothèques et les modèles de thread avancés.
* Initialisation du système : Le processus init (PID 1) est l'ancêtre de tous les autres processus du système. Il est responsable du démarrage d'autres processus lors du démarrage.
* `pthread_create()` : Cette fonction est utilisée pour créer des threads au sein d'un processus. Bien que les threads partagent le même espace mémoire que leur processus parent, ils sont toujours considérés comme des unités d'exécution distinctes gérées par le noyau.
Suppression du processus (résiliation) :
Un processus se termine (est supprimé) dans plusieurs circonstances :
* Résiliation normale : Le processus termine son exécution et appelle l'appel système `exit()`. Cela signale au système d'exploitation qu'il a terminé. Le statut de sortie peut être utilisé pour exprimer le succès ou l’échec.
* Résiliation anormale : Le processus se bloque en raison d'une erreur de segmentation, d'une instruction illégale ou d'une autre erreur. Le noyau termine le processus.
* Terminaison du signal : Un autre processus (ou le noyau lui-même) peut envoyer un signal (par exemple, `SIGTERM`, `SIGKILL`) à un processus, forçant son arrêt. `SIGTERM` permet au processus de nettoyer avant de quitter, tandis que `SIGKILL` termine immédiatement le processus sans aucun nettoyage.
* Fin du processus parent : Si un processus parent se termine, ses processus enfants peuvent également être terminés, en fonction des paramètres du système d'exploitation (souvent hérités du groupe de processus parent). Le processus « init » adopte généralement des enfants orphelins.
Le rôle du noyau :
Le noyau joue un rôle crucial dans la gestion des processus tout au long de leur cycle de vie. Il gère la création de processus, la planification, l'allocation de mémoire, la gestion des ressources, la gestion des signaux et la terminaison des processus. Le noyau maintient des structures de données (comme la table des processus) pour suivre les informations sur chaque processus en cours d'exécution.
En résumé, la création et la suppression de processus sous UNIX sont soigneusement orchestrées par le noyau et impliquent un ensemble d'appels système qui permettent aux programmeurs de contrôler le cycle de vie des processus. Les familles `fork()` et `exec()` (pour la création) et `exit()` et les signaux (pour la suppression) sont les composants principaux.
|