logo

Les fonctions des systèmes d'exploitation

Description rapide et enjeux

L’utilisateur de base d’un ordinateur (ou d’un téléphone, ou d’une console de jeux, etc.) est en général conscient de l’existence de deux types d’entités sur son équipement :

Dans les notes qui suivent nous introduisons des problématiques de gestion de ces types de données et certaines solutions qui existent ou ont pu exister.

Qu’est-ce-qu’un système d’exploitation ?

La réponse à cette question a un léger côté subjectif, mais globalement voici ce qu’on attend d’un système d’exploitation :

Dans ces notes on s’intéresse essentiellement à certains mécanismes mis en œuvre par les systèmes de type UNIX pour atteindre ces buts. Les systèmes modernes sont beaucoup plus compliqués que ce que nous décrirons (par exemple dans ces notes ne seront pas évoqués les systèmes multi-processeurs ou les problématiques liées au cloud), mais les questions posées ici sont toujours d’actualité.

On peut schématiser le fonctionnement d’un ordinateur à l’aide de couches qui communiquent entre elles de la façon suivante :

Si un processus tente d’accéder au matériel, alors qu’il n’en a pas l’autorisation, le noyau tue ce processus (c’est le fameux segmen-tation fault que peuvent rencontre les programmeurs C).

Ressources et mémoire

Pour comprendre tous les mécanismes déployés par un système d’exploitation, il faut avoir en tête le schéma concernant les divers types de mémoire sur un ordinateur, présenté en figure 1.

registres emplacement mémoire interne à un processeur, rapide d’accès mais petits (quelques dizaines d’octets en général)

caches également sur le processeur, sert à stocker temporairement des instructions ou des données et à accélérer les traitements en limitant les accès à la mémoire vive (accéder au cache : 5 à 10 fois plus rapide qu’accéder à la ram)

mémoire vive/ram mémoire volatile, assez rapide d’accès (taille : de l’ordre du Go)

Le noyau a intérêt à avoir sous la main, c’est-à-dire dans la mémoire la plus rapide d’accès (au plus haut dans le schéma de la figure 1), les données dont il a besoin. De façon générale, quand le noyau a besoin d’une ressource (un fichier ou un exécutable par exemple), il la rapatrie dans la mémoire volatile. Il travaille sur cette ressource et, si besoin, met à jour la mémoire permanente par la suite. C’est ce qui explique que si un ordinateur s’éteind d’un coup et qu’on n’a pas sauvegardé le contenu d’un traitement de texte par exemple, on ne retrouve pas tout ce qui a été écrit au moment du redémarrage.

Malheureusement, plus la mémoire est rapide, plus elle est chère et donc plus sa capacité est réduite. Il est donc impossible de mettre les contenus de tous les fichiers par exemple dans la mémoire volatile ; une partie du travail du système d’exploitation est de gérer le contenu de la mémoire volatile, mais aussi de faire en sorte que les applications ignorent où se trouvent les données qu’elles traitent.

Ce qui fait la vitesse d’un ordinateur ce n’est pas tant que la rapidité du CPU que la taille du cache : le CPU peut être aussi rapide qu’on veut, s’il n’y a pas de cache la machine sera lente. Pourquoi alors ne pas mettre les moyens et faire un cache beaucoup plus grand ? Ce serait au bout d’un moment préjudiciable au niveau rapidité puisque plus une ressource est grande, plus c’est compliqué de trouver des données à l’intérieur.

Fichiers et I-nœuds

Les chaînes de caractères ne sont pas des objets pratiques à manipuler (on peut penser notament à tous les problèmes de sto-ckages et de recherche). C’est pourquoi le système identifie les fichiers non par un nom (ce qui est pratique pour l’être humain, mais pas pour la machine), mais par un nombre, appelé numéro d’i-nœud. L’i-nœud (inode en anglais) est une entité qui regroupe un certain nombre de données nécessaires à l’accès à un fichier (par exemple le propriétaire, les droits, l’emplacement où se trouve les données du fichier). Le nom du fichier est en fait complètement indépendant de l’ensemble des données qu’il contient. Le lien entre l’i-nœud du système et le nom attribué par l’utilisateur se situe dans le contenu du répertoire dans lequel “se trouve” le fichier : le contenu d’un répertoire est une liste de paires (nom, numéro d’i-nœud) ; la suppression d’un fichier est en fait la suppression d’une paire dans cette liste, c’est donc la modification du contenu d’un répertoire : cela explique que le droit associé à cette action soit un droit d’écriture sur le répertoire.

Déplacer un fichier d’un répertoire à un autre revient à modifier les listes associées aux deux répertoires : supprimer une paire dans le répertoire origine et en ajouter une dans le répertoire destination. Il y a donc très peu de données manipulées, contrairement à ce qui se passe lors d’une copie d’un fichier. On peut le voir de façon empirique :

pi@raspberry:~ $ ls -lh image.iso
-rw-rw-r-- 1 moi mon_groupe 764M mai   17  2018 image.iso
pi@raspberry:~ $ time cp image.iso copie.iso  #time mesure divers temps associés à un processus
real	0m0,757s
user	0m0,000s
sys 0m0,432s
pi@raspberry:~ $ time mv image.iso /tmp/bouge.iso
real	0m0,002s
user	0m0,002s
sys 0m0,000s

En fait sur un système de type UNIX, un fichier peut avoir plusieurs noms (voir la commande ln), voire aucun : on peut en faire l’expérience en lançant la lecture d’un fichier vidéo avec un logiciel ad hoc et en supprimant ce fichier en ligne de commande : la lecture de la vidéo continue, ce qui signifie que le fichier existe encore, et pourtant il n’a plus de nom. Une fois le logiciel de visionnage fermé, on n’a plus accès au fichier par le SGF : les données existent quelque part sur le disque et en mémoire tant que les emplacements où elles se trouvent n’ont pas été utilisés pour y mettre de nouvelles données, mais l’utilisateur n’y a plus accès (au moins de façon simple ; il existe des programmes qui analysent les données d’un disque pour tenter de récupérer des fichiers effacés 3).

Les numéros d’i-nœud sont obtenus grâce à l’option -i de la commande ls. Le numéro d’i-nœud de la racine est toujours 2.

Un i-nœud contient toutes les informations concernant un fichier, sauf son nom. Il existe en fait deux types d’i-nœuds :

Tout le travail se fait en mémoire. Quand l’utilisateur fait une sauvegarde, les modifications sont alors recopiées sur le disque.

Supposons qu’un utilisateur veuille modifier un fichier avec un éditeur de texte : il le désigne par son nom. Le système trouve alors le numéro d’i-nœud associé en parcourant le répertoire qui contient le fichier. Si l’i-nœud ne se trouve pas en mémoire, le système le charge en mémoire, puis vérifie les droits d’accès. Le système transmet alors un descripteur correspondant à une ouverture du fichier.

Processus

Les systèmes de type UNIX sont multi-tâches : l’utilisateur a l’impression que plusieurs tâches peuvent s’exécuter en même temps. Un processeur ne peut pourtant exécuter qu’un seul processus à la fois, qu’on appelle processus actif. L’ensemble de la mémoire associé à un processus (le code qu’il exécute, la pile d’appel, les données, le compteur qui lui permet de savoir où il en est de son exécution, etc.) est appelé son contexte. L’ordonnanceur change régulièrement de processus actif en procédant à un changement de contexte. Ainsi le nouveau processus actif n’a pas conscience qu’il a été interrompu et continue là où il en était.

Un des algorithmes classiques d’ordonnancement de processus est appelé round robin. On peut imaginer que les processus sont rangés dans une liste chaînée circulaire et à chaque tic d’horloge l’ordonnanceur donne la main au processus suivant dans cette liste. Si le processus se termine avant le tic suivant, il est supprimé de la liste, sinon il y reste.

Systèmes propriétaires vs. systèmes libres

Il existe divers systèmes d’exploitation et tous n’apportent pas les mêmes solutions aux questions de la section 1.1. Indépendem-ment des solutions apportées, il existe deux familles de systèmes : les systèmes propriétaires et les systèmes libres. La différence essentielle est que le code d’un logiciel libre (et donc d’un système libre) est public. On peut en général le modifier ou s’en servir pour fabriquer de nouveaux produits (il est quand même prudent de connaître la licence sous laquelle le logiciel a été publié qui peut préciser ces droits et des obligations du type citer les auteurs originaux ou non, pourvoir fabriquer des logiciels propriétaires ou non, etc.). Les logiciels propriétaires sont en général non ouverts, il est donc plus difficile (voire illégal) de les modifier. Les logiciels libres sont souvent maintenus par la communauté, mais peuvent aussi l’être par des entreprises qui les utilisent et qui ont intérêt à ce qu’ils restent efficaces et utilisés par d’autres, ce qui assure l’existence de développeurs susceptibles de participer à leur maintien. Les logiciels propriétaires quant à eux sont essentiellement développés et mis à jour par l’entreprise qui les possède et qui peut décider d’arrêter de les maintenir. Ce sont deux modèles économiques très différents.