Utilisateur:Topeil/Principes des systèmes d'exploitation/Processus
Gestion des processus
[modifier | modifier le wikicode]Il est utile de fournir aux processus des moyens d'interagir entre eux, ce qui multiplie les possibilités pour le programmeur. Entre autres, il appartient au système d'exploitation de leur permettre de :
- Créer des processus annexes ; ceci est d'autant plus important que les machines possèdent de plus en plus de processeurs, et peuvent donc les exécuter sans affecter le processus d'origine.
- Communiquer avec ces processus annexes ou des processus externes.
Appels systèmes fournis pour la création de processus
[modifier | modifier le wikicode]Le lancement d'un programme
[modifier | modifier le wikicode]Lorsque l’on a besoin d'un programme extérieur, il faut un moyen de l'exécuter, ce qui est fait via un appel système, comme l'appel "exec" sur les systèmes UNIX.
La duplication complète : "fork"
[modifier | modifier le wikicode]La solution la plus classique pour la création de processus annexes reste la duplication pure et simple du programme courant : on obtient ainsi deux programmes, un père et un fils, qui possèdent au départ le même état, mais qui pourront diverger, par exemple si le programmeur prévoit des fonctions différentes pour chacun d'eux. Cet appel est un incontournable pour tout système multitâche. À l'origine, il est disponible sous le nom de "fork" ("fourchette" en Anglais) sur les systèmes de type UNIX, mais il existe des appels équivalents sur presque tous les autres. Le problème est que copier entièrement le processus est particulièrement lourd : il faut copier sa mémoire, ses accès aux fichiers, sa pile... On peut accélérer cette opération en ne recopiant que les endroits où le processus fils écrit, au fur et à mesure, mais cela reste coûteux en temps.
Création de processus légers
[modifier | modifier le wikicode]Les processus légers, ou "threads", ne sont pas à proprement parler des processus : contrairement à ceux-ci, ils ne possèdent pas leur propre espace de mémoire, ni leurs propres accès aux fichiers. En revanche, ils possèdent chacun leur propre pile, et s'exécutent concurremment : un programme peut en utiliser pour remplir des fonctions annexes, ou au contraire pour utiliser plusieurs processeurs à la fois pour accélérer ses calculs. Un unique processus peut ainsi créer plusieurs processus légers, beaucoup plus rapidement que s'il se dupliquait. Ils sont ordonnancés comme des processus par le système, mais demandent une gestion efficace des priorités : un processus utilisant de nombreux threads ne doit pas monopoliser le processeur.
Solutions intermédiaires
[modifier | modifier le wikicode]Bien sûr, il est possible d'imaginer des façons intermédiaires de paralléliser les tâches, par exemple en ne dupliquant qu'une partie de la mémoire, plutôt que l’opposition "tout ou rien" entre les processus légers et la duplication du processus. On peut ainsi décider de ne dupliquer que la mémoire, ou que les accès aux fichiers.
Interactions entre processus
[modifier | modifier le wikicode]Passage de messages
[modifier | modifier le wikicode]Pipes et files
[modifier | modifier le wikicode]Verrous
[modifier | modifier le wikicode]Certaines variables ne peuvent être accédées que par un processus ou un thread simultanément, pour éviter qu'elle soit modifiée par un thread s'exécutant concurremment. Cela est possible en fournissant un mécanisme de verrouillage ; un verrou peut prendre deux états : ouvert ou fermé. Un thread peut le bloquer : il prend possession du verrou et le ferme si celui-ci est ouvert ; sinon, il attend jusqu'à ce que le thread qui le possède le débloque. Quand il n'a plus besoin du verrou, il le débloque à son tour, ce qui permet aux autres threads de l’utiliser.
Mémoire partagée
[modifier | modifier le wikicode]La mémoire partagée est un moyen rapide de partager des données : il s'agit d'une zone de mémoire qui, au lieu d'appartenir à un processus en particulier, est commune à plusieurs, qui peuvent tous y accéder. Ainsi, des données peuvent être mises en commun sans la perte de temps que représente un passage par un appel système.
Sur les machines multiprocesseurs, elle est plus ou moins facile à mettre en place : les ordinateurs à accès symétrique à la mémoire, dits SMP (symetric multiprocessing), possèdent une unique mémoire globale. Une partie de celle-ci peut donc être partagée entre plusieurs processus, car elle est a priori aussi facile d'accès pour tous. Cependant, le processeur possède une mémoire cache, qui retient les parties de la mémoire dernièrement accédées ; utiliser de la mémoire partagée demande de mettre à jour le cache pour chaque processeur lorsqu'un emplacement de cette mémoire est modifié. Selon les types de processeur, cela pourra être le cas, auquel cas le système d'exploitation ne s'en occupe que pour des raisons d'optimisation, ou alors il faut empêcher le cache de retenir les données en mémoire partagée. Les systèmes pour lesquels la mémoire n’est pas unique, mais peut être répartie en plusieurs endroits (NUMA, pour non-uniform memory access), posent des problèmes pour la mémoire partagée : tous les processeurs n'y accèdent pas de la même manière, et elle peut devenir lente lorsque l'un des processus accède à une zone de mémoire qui n’est pas directement accessible par le processeur où il s'exécute actuellement.