Systèmes d'exploitation : Trois pièces faciles. Partie 2 : Abstraction : Processus (traduction)

Introduction aux systèmes d'exploitation

Bonjour, Habr ! Je souhaite vous présenter une série d'articles traduits d'une littérature que je trouve intéressante — OSTEP. Ce matériel explore en profondeur le fonctionnement des systèmes d'exploitation de type Unix, en particulier — le travail avec les processus, les différents planificateurs, la mémoire et d'autres composants similaires qui forment un système d'exploitation moderne. Vous pouvez voir l'original de tous ces matériaux ici ici. Je vous demande de prendre en compte que la traduction a été réalisée de manière non professionnelle (assez libre), mais j'espère que le sens général a été conservé.

Les travaux pratiques sur ce sujet peuvent être trouvés ici :

Autres parties :

Vous pouvez également visiter ma chaîne sur Telegram =)

Considérons l'abstraction la plus fondamentale que le système d'exploitation fournit aux utilisateurs : le processus. La définition d'un processus est assez simple — c'est un programme en cours d'exécution. Un programme en lui-même est une chose inanimée, située sur le disque — c'est un ensemble d'instructions et peut-être quelques données statiques, attendant le moment de son lancement. C'est le système d'exploitation qui prend ces octets et les exécute, transformant le programme en quelque chose d'utile.
Le plus souvent, les utilisateurs veulent exécuter plusieurs programmes simultanément, par exemple, vous pouvez lancer sur votre ordinateur portable un navigateur, un jeu, un lecteur multimédia, un éditeur de texte, etc. En fait, un système typique peut exécuter des dizaines, voire des centaines de processus en même temps. Ce fait rend le système plus facile à utiliser, vous n'avez jamais à vous soucier de savoir si le CPU est libre, vous lancez simplement les programmes.

Ceci soulève une question : comment créer l'illusion de plusieurs CPU ? Comment le système d'exploitation peut-il générer l'illusion d'un nombre pratiquement infini de CPU, même si vous n'avez qu'un seul CPU physique ?

Le système d'exploitation crée cette illusion grâce à la virtualisation du CPU. En lançant un processus, puis en l'arrêtant, en lançant un autre processus, et ainsi de suite, le système d'exploitation peut maintenir l'illusion qu'il existe de nombreux CPU virtuels, même si en réalité il n'y a qu'un ou quelques processeurs physiques. Cette technique est appelée partage des ressources CPU dans le temps. Cette technique permet aux utilisateurs d'exécuter autant de processus simultanément qu'ils le souhaitent. Le prix de cette solution est la performance — car si plusieurs processus partagent le CPU, chaque processus sera traité plus lentement.
Pour mettre en œuvre la virtualisation du CPU, et surtout pour le faire correctement, le système d'exploitation a besoin d'un soutien à la fois bas niveau et haut niveau. Le soutien de bas niveau est appelé mécanismes — ce sont des méthodes ou protocoles de bas niveau qui mettent en œuvre la partie nécessaire de la fonctionnalité. Un exemple de cette fonctionnalité est le changement de contexte, qui permet au système d'exploitation d'arrêter un programme et de lancer un autre programme sur le processeur. Cette séparation temporelle est réalisée dans tous les systèmes d'exploitation modernes.
Au sommet de ces mécanismes se trouve une certaine logique, intégrée dans le système d'exploitation, sous forme de "politiques". Politique — est un certain algorithme de prise de décision du système d'exploitation. Ces politiques, par exemple, décident quel programme doit être lancé (parmi la liste des commandes) en premier. Ainsi, par exemple, cette tâche sera résolue par une politique appelée politique de planification (scheduling policy) et lors du choix de la solution, elle sera guidée par des données telles que : l'historique des lancements (quel programme a été lancé le plus longtemps au cours de la dernière minute), quelle charge exerce ce processus (quels types de programmes ont été lancés), les métriques de performance (le système est-il optimisé pour une interaction interactive ou pour la bande passante) et ainsi de suite.

Abstraction : processus

L'abstraction d'un programme en cours d'exécution, exécutée par le système d'exploitation, est ce que nous appelons processus. Comme déjà mentionné, un processus est simplement un programme en cours d'exécution à tout moment donné. C'est un programme grâce auquel nous pouvons obtenir des informations globales provenant de diverses ressources du système, et auxquelles ce programme accède ou que ce programme affecte lors de son exécution.
Pour comprendre les éléments constitutifs d'un processus, il est nécessaire de comprendre les états du système : ce que le programme peut lire ou modifier pendant son fonctionnement. À tout moment, il faut comprendre quels éléments du système sont importants pour l'exécution du programme.
L'un des éléments évidents de l'état du système, que le processus inclut, est la mémoire. Les instructions sont situées dans la mémoire. Les données que le programme lit ou écrit se trouvent également dans la mémoire. Ainsi, la mémoire que le processus peut adresser (ce qu'on appelle l'espace d'adressage) est une partie du processus.
L'état du système comprend également les registres. De nombreuses instructions sont destinées à modifier la valeur des registres ou à lire leur valeur, rendant ainsi les registres une partie importante du fonctionnement du processus.
Il convient de noter que l'état de la machine est également constitué de certains registres spéciaux. Par exemple, IP — pointeur d'instruction — qui indique l'instruction que le programme exécute actuellement. Il y a aussi pointeur de pile et son associé pointeur de cadre, qui sont utilisés pour la gestion : des paramètres de fonction, des variables locales et des adresses de retour.
Enfin, les programmes accèdent souvent à la ROM (mémoire morte). Ces informations sur l'"I/O" (entrée-sortie) doivent inclure une liste des fichiers actuellement ouverts par le processus.

API des processus

Pour mieux comprendre le fonctionnement des processus, examinons des exemples d'appels système qui devraient être inclus dans toute interface de système d'exploitation. Ces API sont disponibles sous une forme ou une autre sur tout système d'exploitation.

● Créer (création) : Le système d'exploitation doit inclure une méthode permettant de créer de nouveaux processus. Lorsque vous entrez une commande dans le terminal ou lancez une application en double-cliquant sur son icône, un appel est envoyé au système d'exploitation pour créer un nouveau processus et lancer le programme spécifié.
● Désinstallation: Étant donné qu'il existe une interface pour créer un processus, le système d'exploitation doit également fournir la possibilité de forcer la suppression d'un processus. La plupart des programmes seront naturellement lancés et terminés d'eux-mêmes au fur et à mesure de leur exécution. Sinon, l'utilisateur souhaiterait pouvoir les tuer, et ainsi l'interface pour arrêter un processus serait utile.
● Attente (attente) : Parfois, il est utile d'attendre la fin d'un processus, c'est pourquoi certaines interfaces sont fournies pour attendre.
● Contrôle Divers (contrôle varié) : En plus de tuer et d'attendre un processus, il existe également d'autres méthodes de contrôle. Par exemple, la plupart des systèmes d'exploitation offrent la possibilité de suspendre un processus (arrêter son exécution pendant un certain temps) puis de le reprendre (continuer l'exécution).
● Statut (état) : Il existe différentes interfaces pour obtenir certaines informations sur l'état du processus, telles que sa durée d'exécution ou l'état actuel dans lequel il se trouve.

Systèmes d'exploitation : Trois pièces faciles. Partie 2 : Abstraction : Processus (traduction)

Création de processus : détails

L'une des choses intéressantes est de comprendre comment les programmes se transforment en processus. En particulier, comment le système d'exploitation charge et exécute un programme. Comment un processus est-il créé concrètement ?
Tout d'abord, le système d'exploitation doit charger le code du programme et les données statiques en mémoire (dans l'espace d'adressage du processus). Les programmes sont généralement stockés sur un disque ou un SSD dans un certain format exécutable. Ainsi, le processus de chargement du programme et des données statiques en mémoire nécessite que le système d'exploitation soit capable de lire ces octets à partir du disque et de les placer quelque part en mémoire.

Dans les anciens systèmes d'exploitation, le processus de chargement se faisait de manière impatiente (eagerly), c’est-à-dire que le code était chargé dans la mémoire entièrement avant que le programme ne soit exécuté. Les systèmes d'exploitation modernes effectuent cela de manière paresseuse (lazily), c'est-à-dire qu'ils chargent des morceaux de code ou de données uniquement au moment où ils sont nécessaires pendant l'exécution du programme.

Après que le code et les données statiques sont chargés en mémoire, le système d'exploitation doit encore accomplir certaines tâches avant de lancer le processus. Une certaine quantité de mémoire doit être allouée pour la pile. Les programmes utilisent la pile pour les variables locales, les paramètres de fonction et les adresses de retour.. Le système d'exploitation réserve cette mémoire et la donne au processus. La pile peut également être allouée avec certains arguments, en particulier elle remplit les paramètres de la fonction main(), tels que le tableau argc et argv.

Le système d'exploitation peut également allouer une certaine quantité de mémoire pour le tas (heap) du programme. Le tas est utilisé par les programmes pour les données dynamiquement allouées demandées explicitement.. Les programmes demandent cet espace en appelant la fonction malloc() et le libèrent explicitement en appelant la fonction free(). Le tas est nécessaire pour des structures de données telles que : les listes chaînées, les tables de hachage, les arbres et d'autres. Au début, une petite quantité de mémoire est allouée au tas, mais au fil du temps, au cours de l'exécution du programme, le tas peut demander plus de mémoire via l'appel à l'API de bibliothèque malloc(). Le système d'exploitation est impliqué dans le processus d'allocation de plus de mémoire pour satisfaire ces demandes.

Le système d'exploitation effectuera également des tâches d'initialisation, en particulier celles liées à l'entrée-sortie. Par exemple, dans les systèmes UNIX, chaque processus a par défaut 3 descripteurs de fichiers ouverts, pour le flux d'entrée standard, la sortie et les erreurs. Ces descripteurs permettent aux programmes de lire l'entrée du terminal et d'afficher des informations à l'écran.

Ainsi, en chargeant le code et les données statiques en mémoire, en créant et en initialisant la pile, ainsi qu'en effectuant d'autres tâches liées aux opérations d'entrée-sortie, le système d'exploitation prépare le terrain pour l'exécution du processus. En fin de compte, il reste une dernière tâche : exécuter le programme via son point d'entrée, appelé fonction main(). En passant à l'exécution de la fonction main(), le système d'exploitation passe le contrôle du CPU au nouveau processus, ainsi, le programme commence à s'exécuter.

L'état du processus

Maintenant que nous avons une certaine compréhension de ce qu'est un processus et comment il est créé, énumérons les états dans lesquels un processus peut se trouver. Dans sa forme la plus simple, un processus peut être dans l'un de ces états :
● Running. Dans l'état en cours d'exécution, le processus s'exécute sur le processeur. Cela signifie que des instructions sont en cours d'exécution.
● Prêt. Dans l'état prêt, le processus est prêt à être exécuté, mais pour une raison quelconque, le système d'exploitation ne l'exécute pas à ce moment-là.
● Bloqué. Dans l'état bloqué, le processus effectue certaines opérations qui l'empêchent d'être prêt à s'exécuter jusqu'à ce qu'un événement se produise. Un exemple courant est lorsqu'un processus initialise une opération d'E/S, il devient bloqué et, de ce fait, un autre processus peut utiliser le processeur.

Systèmes d'exploitation : Trois pièces faciles. Partie 2 : Abstraction : Processus (traduction)

On peut visualiser ces états sous la forme d'un graphe. Comme nous pouvons le voir sur l'image, l'état d'un processus peut changer entre RUNNING et READY à la discrétion du système d'exploitation. Lorsque l'état d'un processus passe de READY à RUNNING, cela signifie que le processus a été planifié. En revanche, cela signifie qu'il a été retiré de la planification. Au moment où le processus devient BLOCKED, par exemple en initialisant une opération d'entrée/sortie, le système d'exploitation le maintiendra dans cet état jusqu'à ce qu'un événement se produise, comme la fin de l'opération d'entrée/sortie. À ce moment-là, il passera à l'état READY et éventuellement à l'état RUNNING, selon la décision du système d'exploitation.
Jetons un œil à un exemple de la manière dont deux processus passent à travers ces états. Pour commencer, supposons que les deux processus sont en cours d'exécution et que chacun utilise uniquement le CPU. Dans ce cas, leurs états apparaîtront comme suit.

Systèmes d'exploitation : Trois pièces faciles. Partie 2 : Abstraction : Processus (traduction)

Dans l'exemple suivant, le premier processus, après un certain temps d'exécution, demande une entrée/sortie et passe à l'état BLOCKED, donnant à un autre processus la chance de s'exécuter (FIG 1.4). Le système d'exploitation voit que le processus 0 n'utilise pas le CPU et lance le processus 1. Pendant l'exécution du processus 1, l'entrée/sortie se termine et l'état du processus 0 passe à READY. Enfin, le processus 1 se termine et, après son achèvement, le processus 0 est lancé, s'exécute et finit son travail.

Systèmes d'exploitation : Trois pièces faciles. Partie 2 : Abstraction : Processus (traduction)

Structure des données

Le système d'exploitation est lui-même un programme, et comme tout autre programme, il a certaines structures de données clés qui suivent divers morceaux d'information pertinents. Pour suivre l'état de chaque processus, le système d'exploitation maintiendra une certaine liste des processus pour tous les processus dans l'état READY et des informations supplémentaires pour suivre les processus qui s'exécutent actuellement. De plus, le système d'exploitation doit suivre les processus bloqués. Après la fin de l'entrée/sortie, le système d'exploitation doit réveiller le processus concerné et le passer à l'état prêt à être exécuté.

Ainsi, par exemple, le système d'exploitation doit conserver l'état des registres du processeur. Au moment où le processus est suspendu, l'état des registres est enregistré dans l'espace d'adressage du processus, et au moment de la reprise de son exécution, les valeurs des registres sont restaurées et le processus peut ainsi continuer son exécution.

En plus des états prêt, bloqué et en cours d'exécution, il existe d'autres états. Parfois, au moment de la création, un processus peut avoir l'état INIT. Enfin, le processus peut être placé dans l'état FINAL, une fois qu'il est terminé, mais que les informations à son sujet n'ont pas encore été nettoyées. Dans les systèmes UNIX, cet état est appelé processus zombie. Cet état est utile lorsque le processus parent souhaite connaître le code de retour de son enfant, par exemple, généralement 0 signale une réussite, et 1 un échec, mais les programmeurs peuvent créer des codes de sortie supplémentaires pour signaler différents problèmes. Lors de la terminaison, le processus parent effectue le dernier appel système, par exemple wait(), pour attendre la fin du travail du processus enfant et signaler au système d'exploitation qu'il peut nettoyer les données associées au processus terminé.

Systèmes d'exploitation : Trois pièces faciles. Partie 2 : Abstraction : Processus (traduction)

Points clés de la leçon :

● Processus — l'abstraction principale d'un programme en cours d'exécution dans un système d'exploitation. À tout moment, un processus peut être décrit par son état : le contenu de la mémoire dans son espace d'adresses, le contenu des registres du processeur, y compris le pointeur d'instruction et le pointeur de pile, ainsi que les informations sur les E/S, comme les fichiers ouverts qui sont lus ou écrits.
● API des processus se compose d'appels que les programmes peuvent faire concernant les processus. Généralement, ce sont des appels de création, de suppression ou d'autres.
● Un processus se trouve dans l'un des nombreux états, y compris en cours d'exécution, prêt, bloqué. Différents événements, tels que la planification, une exception de planification ou une attente, peuvent faire passer l'état d'un processus d'un état à un autre.
● Liste des processus contient des informations sur tous les processus du système. Chaque entrée est appelée bloc de contrôle de processus, qui est en réalité une structure contenant toutes les informations nécessaires sur un processus particulier. 

Source : habr.com

Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS 🔥 Acheter un hébergement fiable pour les sites avec protection DDoS, serveurs VPS VDS | ProHoster