À quoi sert un système d’exploitation ?
Le manchot est le symbole de Linux, système d’exploitation libre très populaire.
L’informatique est une science jeune, avec beaucoup d’aspects techniques et une forte compétition industrielle. Aujourd’hui, il existe un système d’exploitation dans chaque ordinateur, tablette, téléphone portable, et plus généralement tout objet numérique, avec sur le marché des dizaines de systèmes d’exploitation différents. Dans leur nom, on trouve souvent le sigle OS pour Operating System, en anglais. Même si les constructeurs utilisent des noms différents pour se démarquer de leurs concurrents, on retrouve dans tous les systèmes d’exploitation des aspects communs et des invariants.
D’un ordinateur ou d’une tablette, on voit d’abord l’écran et le boîtier qui enferme le matériel informatique — processeurs, mémoires et canaux d’entrées-sorties —, mais c’est le logiciel qu’il contient que l’on utilise.
La programmation directe de l’ordinateur est laborieuse. La machine, construite sur le modèle de Von Neumann, est universelle (voir sur Interstices Sous le signe du calcul, par Jean-Louis Giavitto et François Rechenmann et Alan Turing : du concept à la machine, par Sacha Krakowiak). Toutefois, le langage qu’elle reconnaît, composé d’instructions et de données, toutes codées en binaire, est très difficile d’emploi. Le système d’exploitation vient alors au secours de l’utilisateur, en lui permettant d’exploiter l’ordinateur mieux qu’en langage machine. Mais il fait plus que cela.
Rôles du système d’exploitation
Le but d’un système d’exploitation est de rendre aisée l’utilisation de l’ordinateur par chacun, comme s’il s’agissait d’une machine fictive, sa « machine virtuelle », qui aurait été construite pour lui. Le système fournit un accès commode et ergonomique, par exemple avec un écran comportant des fenêtres multiples et une interface graphique. Aujourd’hui, en 2015, il peut aussi y avoir une interface tactile ou sonore.
Le système assure le stockage de programmes et de données de toutes sortes — textes, images, vidéos, films — dans des fichiers préparés par l’utilisateur ou chargés depuis des supports externes ou via le réseau. Idéalement, ce premier rôle de gestion de l’information et des fichiers doit permettre à l’utilisateur de n’avoir à préciser que les aspects logiques de son travail.
Le second rôle du système, le contrôle d’exécution, consiste à gérer au mieux les ressources — matérielles et logicielles — qui sont nécessaires pour lancer et suivre l’exécution des applications locales ou distantes. Le système s’occupe ainsi des aspects technologiques et des contraintes d’utilisation des ressources partagées, qu’elles soient attribuées à tour de rôle, comme le sont le processeur et l’imprimante, ou divisées, comme le sont la mémoire et l’écran.
Ces deux rôles doivent être pérennes. Pour cela, le système d’exploitation assure — et c’est là son troisième rôle — la sécurité de fonctionnement en cas de panne d’origine interne (matérielle ou logicielle) ou d’agression provenant d’un environnement de plus en plus ouvert (le réseau). Il sauvegarde automatiquement les travaux en cours et veille à permettre le redémarrage après une panne. Il doit aussi rendre possible une évolution matérielle (changement dans la configuration matérielle) ou fonctionnelle (mise à jour et ajout de programmes).
Ces rôles sont remplis par des services décrits dans les programmes du système d’exploitation ; l’exécution de ces programmes — et donc des services — est accomplie par les processus du système d’exploitation.
Un programme est une entité passive, décrivant une suite d’instructions. Un processus est son pendant dynamique, une entité active qui représente l’exécution de cette suite d’instructions par l’ordinateur.
Représentations du système d’exploitation d’un ordinateur
Un système d’exploitation peut être considéré selon deux points de vue :
- une vision « statique » qui correspond à l’empilement hiérarchique de ses programmes,
- une vision « dynamique » qui rend compte de l’exécution des programmes par les processus.
Représentation statique par les programmes
Le système d’exploitation d’un ordinateur est un fantastique regroupement de programmes et de données qui ont été élaborés pour fournir les services requis pour chacun des rôles cités précédemment. Ces informations sont empilées astucieusement en couches qui reflètent la forte structuration de la construction : au niveau le plus bas, on trouve les programmes du noyau qui matérialisent les principes sur lesquels est fondée la construction du système, puis les programmes qui pilotent l’accès au matériel ; au-dessus, dans l’ordre ascendant, utilisant parfois les programmes des couches qui leur sont sous-jacentes, viennent les services propres du système d’exploitation, les services communautaires, et enfin les programmes d’application destinés à l’utilisateur.
La construction d’un système d’exploitation s’appuie sur le schéma de Von Neumann – le programme enregistré en mémoire et la mémoire adressable –, et sur deux extensions importantes : le sous-programme et l’interruption. Ces spécificités sont utilisées dans les systèmes d’exploitation, comme dans tout logiciel de grande taille, pour créer des couches et des empilements structurés de programmes et de données.
Le processeur prend ses instructions et ses données dans la mémoire centrale et modifie celle-ci en y inscrivant les résultats, qui peuvent être des données ou de nouvelles instructions.
La mémoire est adressable, c’est-à-dire que son contenu n’est accessible à un processeur que par une adresse dans une instruction. L’adresse est une donnée comme une autre, stockée en mémoire, et on peut faire des calculs d’adresse et définir ainsi divers chemins d’accès à l’information suivant une hiérarchie et des contrôles qui permettent de structurer le rangement et la recherche des informations.
Le sous-programme a été inventé par David Wheeler pour l’EDSAC, premier ordinateur à programme enregistré construit à l’université de Cambridge en Grande-Bretagne entre 1946 et 1949. On retrouve des concepts similaires au niveau des langages, avec les concepts de fonction ou de procédure. Un sous-programme permet de construire une suite d’instructions qui est réutilisable et paramétrable et qu’on peut appeler comme un service, autant de fois que c’est utile. On utilise des sous-programmes pour mettre en mémoire des programmes déjà construits et s’en servir de proche en proche pour élaborer à volonté des programmes de plus en plus complexes.
L’interruption de programme a été introduite en 1956 dans le calculateur Univac 1103A. Le mécanisme câblé d’interruption permet de dérouter un processeur qui déroule un programme donné et de le détourner vers l’exécution d’un sous-programme spécifique capable de sauvegarder le contexte d’exécution du programme interrompu et d’attribuer le processeur à un autre programme. Cette interruption est déclenchée par un signal externe au programme en cours. Dans les systèmes, ce mécanisme est utilisé pour le partage des processeurs entre les processus grâce à un signal d’interruption généré par un top d’horloge programmé.
La figure ci-dessous schématise la représentation habituelle de ces services.
Cet empilement structuré d’informations forme une grande base de données : les fichiers du système. Il faut y ajouter les fichiers des utilisateurs entreposés sur des supports gérés par le système d’exploitation ou accessibles à distance sur le réseau.
La rapidité des processeurs et la très grande capacité de la mémoire permettent de construire des systèmes très complexes et de taille considérable qui peut atteindre une dizaine de gigaoctets. Par exemple, un système d’exploitation utilisé pour un ordinateur portable, le système d’exploitation Mac OS X 10.6, occupe environ 5 Go en mémoire auxquels s’ajoutent de 5 à 15 Go pour les bibliothèques partagées.
Représentation dynamique par les processus
De nombreux programmes du système qui ont leurs sources — codes et données — dans ces empilements de couches sont appelés à s’exécuter de façon concomitante. Ils répondent en temps réel aux besoins explicites ou implicites des utilisateurs et réagissent aux événements aléatoires provenant de l’environnement. Quelquefois c’est le même service qui est demandé simultanément par plusieurs événements ou plusieurs utilisateurs. Le système d’exploitation peut ainsi être amené à gérer l’exécution concurrente de plusieurs centaines de programmes. Le mot concurrent, polysémique, évoque à la fois la simultanéité — les programmes courent ensemble — et la compétition dans l’attribution des ressources.
Afin de repérer ces différentes exécutions concomitantes, le terme de processus a été introduit. Ce mot a été utilisé dès 1960 dans le système Multics. Il sert à identifier le déroulement d’un programme séquentiel, parmi d’autres, et le distingue du texte du programme.
À l’origine de l’informatique, puis des systèmes, l’utilisation de la machine était séquentielle. On ne parlait pas encore de processus, car on s’attachait principalement aux algorithmes de calcul et à leur résultat obtenu par l’exécution d’un programme. Le système traitait un programme à la fois et ne considérait pas de parallélisme entre des suites d’opérations de la machine.
La situation a changé quand du parallélisme a été introduit. On s’est mis à traiter les entrées d’un programme avec ses données et les sorties avec ses résultats en parallèle avec le calcul d’un autre programme. Puis, avec l’apparition de mémoires plus grandes, le système d’exploitation a pu mettre en mémoire centrale plusieurs programmes à la fois pour les « multiprogrammer ». Quand ceux-ci ont pu partager des codes communs comme les compilateurs ou des bibliothèques de sous-programmes, il a été nécessaire de distinguer les exécutions concurrentes de ce compilateur ou de ces sous-programmes. Pour les systèmes interactifs ou transactionnels ayant plusieurs utilisateurs devant des écrans ou pour les systèmes réactifs chargés de contrôler des organes physiques externes (dits aussi systèmes temps réel), il a fallu gérer l’exécution parallèle et interactive de programmes qui demeurent permanents le temps d’une session de l’utilisateur, ou qui sont indéfiniment cycliques, pour assurer le contrôle d’organes physiques. L’apparition des réseaux augmenta encore le nombre de liaisons asynchrones à gérer en parallèle. Enfin, quand le parallélisme s’est étendu du système et du temps réel vers des applications plus conventionnelles (utilisant des langages comme Ada ou Java, qui permettent de définir des « tâches » concurrentes), il a fallu utiliser dans les programmes un terme pour exprimer l’exécution, dans une multitude d’exécutions parallèles, d’une section de code qui pouvait être plus ou moins longue ou durer indéfiniment. D’où l’introduction de mots comme processus, tâche, process, ou processus léger, fil d’activité, travail, etc.
La figure ci-dessous schématise cette vision dynamique, qui traduit l’activité des processus. On y distingue les processus du système, à savoir les processus chargés des infrastructures et des services communautaires, et les processus créés plus spécialement pour fournir une « machine virtuelle » à chaque utilisateur. Chacun des processus est une abstraction du processeur physique.
Processus et processeurs
La représentation dynamique fait apparaître une nuée de processus, alors même qu’il n’y a pas assez de processeurs physiques pour en attribuer un à chacun. Or les processeurs physiques ont une vitesse environ un million de fois supérieure à la capacité de réaction de l’utilisateur. Cette énorme différence de rapidité est mise à profit pour simuler le parallélisme de déroulement des programmes en partageant les processeurs entre les processus — c’est ce qu’on appelle le pseudo‑parallélisme. Le partage est rythmé par un top d’horloge qui déclenche l’interruption du processus en cours et l’attribution du processeur à un autre processus. Cette attribution est régie par un programme du noyau du système, l’ordonnanceur. La figure ci-dessous montre un exemple de partage d’un processeur (on suppose ici qu’il n’y en a qu’un) entre quatre processus déclenchés simultanément qui l’utilisent l’un après l’autre, par tranches séquentielles successives. L’attribution du processeur par le noyau consomme aussi du temps de processeur.
Conclusion
La complexité des systèmes d’exploitation est grande, elle résulte tant du nombre et de la taille des programmes impliqués que de la multiplicité des processus et de leurs interactions. Cette grande complexité rend illusoire le « zéro défaut » ! Aujourd’hui, on continue à développer de nouveaux systèmes, tout en recherchant l’augmentation de leur sûreté de fonctionnement. Pour cela, on commence à utiliser des techniques automatiques de certification de programmes.
Pour comprendre plus en détail la dynamique d’un système d’exploitation, et découvrir les processus qui se déclenchent au lancement d’un ordinateur, nous vous invitons à lire l’article Le ballet des processus dans un système d’exploitation.
Je remercie Brigitte Kaiser et les relectrices d’Interstices pour leurs conseils judicieux.
Newsletter
Le responsable de ce traitement est Inria. En saisissant votre adresse mail, vous consentez à recevoir chaque mois une sélection d'articles et à ce que vos données soient collectées et stockées comme décrit dans notre politique de confidentialité
Niveau de lecture
Aidez-nous à évaluer le niveau de lecture de ce document.
Votre choix a été pris en compte. Merci d'avoir estimé le niveau de ce document !