SYNTHESE POUR L’EXAMENT UTC 502
Les systèmes d’exploitation et leur noyau
Définition d’un système d’exploitation : Il s’agit d’un programme (logiciel) qui joue le rôle
d’interface entre le matériel et l’utilisateur ; il va permettre de mettre en lien les ressources
matérielles de la machine avec les applications qui tournent dessus.
Le système d’exploitation permet de présenter une machine virtuelle et de partager des
ressources :
Une machine virtuelle transforme un assemblage de composant et de circuit en un appareil
plus utilisable. Il offre une abstraction simple au niveau des entrées et des sorties, de
l’utilisation de la mémoire, de la gestion des fichiers, de la protection et du contrôle des
erreur, de l’interaction entre les différents programmes
Le partage de ressource : Il se fait entre les programmes appelés plus justement les processus.
L’objectif va être d'éviter les conflits d'utilisation de la mémoire, des périphériques
d'entrées/sorties, des interfaces réseau... etc.
Ce travail assurer par le SE permet de mettre de l’ordre dans un chaos potentiel (donner
exemple si trois programme voulait imprimer en même temps sans qu’un ordre soit établi.)
De plus, lorsque l'ordinateur est utilisé par plusieurs usagers (presque tout le temps), le
partage de la mémoire et surtout sa protection demeurent une priorité absolue. En tout temps,
un bon système d'exploitation connaît l'utilisateur d'une ressource, ses droits d'accès, son
niveau de priorité.
Son organisation générale :
Tous les systèmes d’exploitation sont segmentés en plusieurs couches :
Lorsqu'un programme désire accéder à une ressource matérielle, il ne lui est pas nécessaire
d'envoyer des informations spécifiques au périphérique, il lui suffit d'envoyer les informations
au système d'exploitation, qui se charge de les transmettre au périphérique concerné via son
pilote.
Le système d'exploitation est composé d'un ensemble de
logiciels permettant de gérer les interactions avec le matériel.
Parmi cet ensemble de logiciels on distingue généralement les
éléments suivants :
- Le noyau (en anglais kernel) représentant les fonctions
fondamentales du système d'exploitation telles que la
gestion de la mémoire, des processus, des fichiers, des entrées-sorties principales, et
des fonctionnalités de communication.
- L'interpréteur de commande (en anglais shell, traduisez « coquille » par opposition au
noyau) permettant la communication avec le système d'exploitation par l'intermédiaire
d'un langage de commandes, afin de permettre à l'utilisateur de piloter les
périphériques en ignorant tous des caractéristiques du matériel qu'il utilise, de la
gestion des adresses physiques, etc.
Les différents types de noyau : Comme on vient de le voir, la conception d’un kernel exige
de se demander où placer une fonction : profondément dans le kernel, ou encore à l’extérieur
de celui-ci. Ces choix peuvent modifier considérablement le processus de développement
d’un OS.
Nous verrons ces types de noyaux dans le cours :
- Noyaux monolithiques non modulaires et modulaires
- Micro-noyaux
- Noyaux hybrides
- Noyaux temps réel
Les processus sous linux et windows
Un processus (process) est un programme en cours d’exécution dans un ordinateur. C’est une
entité active avec son propre compteur ordinal (instruction pointer) et l’ensemble des
ressources qui lui sont associées. Ces informations sont stockées, pour chaque processus dans
le PCB (process control block).
Le PCB va contenir typiquement :
Valeurs des registres
Variables
Compteurs
Liste des fichiers ouverts et autres ressources accaparées par le processus
Informations pour la gestion de la mémoire
Différence entre programme et processus :
Un programme et un processus sont des termes liés. La principale différence entre programme
et processus est que programme est un groupe d'instructions permettant d'exécuter une tâche
spécifiée alors que le processus est un programme en cours d'exécution. Bien qu'un processus
soit une entité active, un programme est considéré comme passif.
Il existe une relation multiple entre processus et programme, ce qui signifie qu'un programme
peut invoquer plusieurs processus ou, en d'autres termes, plusieurs processus peuvent faire
partie du même programme.
Les états de processus
Un processus est soit :
1. prêt (suspendu par le système d'exploitation)
2. élu (en exécution)
3. bloqué (en attente d'un événement quelconque pour poursuivre)
On voit qu’il y a 3 états fondamentaux dans lesquels un processus peut se retrouver et 4
transitions possibles entre ces états.
De l'état élu, un processus peut se retrouver dans l'état bloqué ou prêt. L'état bloqué arrive
lorsque le processus ne peut plus continuer faute de données et l'état prêt, lorsque le
système d'exploitation décide d’allouer le processeur à un autre processus.
Le va-et-vient des transitions entre élu et prêt est issu de l'ordonnanceur (scheduler) de
processus du système d'exploitation qui partage le temps entre tous les processus présents
dans la mémoire. On verra plus loin l’ordonnanceur, on se rappelle à ce stade que c’est lui
qui décide quel processus tourne sur le processeur, qui « donne leur tour » à chaque
processus.
La transition de élu à prêt survient lorsque le processus en cours, appelons-le « 1234 » (n°de
PID), a épuisé la tranche de temps qui lui avait été allouée ; il perd alors le processeur,
redevient aussitôt prêt (disponible) lorsque la procédure de sauvegarde de ses variables, de ses
registre cpu , environnement, est terminée. Il est placé alors dans la file d'attente des processus
du système.
La transition de prêt à élu du processus « 1234 » se déroule lorsque tous les processus qui
attendent leur tour ont obtenu du temps de processeur et qu'il faut relancer celui-ci.
L'ordonnanceur suit toujours cet ordre ou choisit le processus à lier au processeur selon un
ordre de priorité (on le verra plus loin).
La transition de bloqué à prêt est provoquée lorsque qu'un processus bloqué en attente
d'information reçoit ce qu'il attendait. Il entre dans la file d'attente des processus prêt et attend
son tour.
Un processus est un programme qui s'exécute et qui possède en plus, son compteur ordinal, ses
registres et ses variables (PCB), c'est là toute la subtilité entre programme et processus. La
différence entre un processus et un programme est mince : le processus possède le programme
mais également l'état courant de celui-ci dans la mémoire de l'ordinateur. Le programme est en
fin de compte l’ensemble des fichiers qui, lorsqu’ils sont exécutés, deviennent le processus.
Les interruptions
Voyons maintenant, de façon très simplifiée, comment le système d'exploitation voit à
l'ordonnancement des processus en tenant compte des interruptions.
Supposons qu'un processus utilisateur, nommé pour l'exemple « PID 1234 », est commandé
par un utilisateur pour afficher le contenu d'un fichier. Le processus est créé et placé par le
noyau du système dans la file d'attente des processus avec les autres et démarre lorsqu'il
obtient son temps de processeur, mais très rapidement il doit faire appel au processus de la
lecture sur disque.
Comme les périphériques E/S (disques) sont contrôlés dans les ordinateurs modernes au
moyen d'interruptions matérielles, on doit recourir à ce vecteur d'interruptions contenant des
adresses pour lancer les routines nécessaires aux traitements.
Le compteur ordinal du processus « 1234 » ainsi que les autres variables mentionnées plus
haut sont sauvegardés dans une pile par le mécanisme matériel du traitement (le branchement
au vecteur d’interruptions) des interruptions et ce processus utilisateur passe en mode bloqué
(il attend des données en provenance du disque).
Le traitement de l'accès au disque peut alors commencer et l'ordonnanceur est appelé pour
gérer la file d'attente. Si la priorité du processus de l'accès au disque est plus élevée que celle
des autres processus prêts, celui-ci obtient le temps du processeur, sinon il attend son tour.
Lorsque la lecture sur disque des données demandées par le processus « 1234 » est complétée,
le mécanisme du traitement de cette interruption « disque » se termine et les valeurs du
processus « 1234 », bloqué tout ce temps, sont replacées sur la pile d'exécution. Celui-ci passe
donc à l'état prêt et retourne dans la file d'attente.
La commutation de contexte constitue la réponse du système à l’occurrence d’une
interruption.
On distingue :
Interruptions internes : protection du système et des processus, appelées par
une instruction à l’intérieur d’un programme (overflow, erreur d’adressage,
code opération inexistant, problème de parité, etc.)
Interruptions logiques : permet à un processus utilisateur de faire un appel au
système.
Interruptions externes : déclenchées par une unité électronique (lecteur,
clavier, contrôleur de périphérique, panne de courant, etc.) ou par l’horloge
(hardware externes).
La programmation des procesus
Les processus d’un système peuvent s’exécuter concurremment (en « même temps »), et
doivent pouvoir être créés et détruits dynamiquement. Par conséquent, le SE doit fournir un
mécanisme de création et de destruction de processus.
Un processus peut créer plusieurs nouveaux processus, via des appels système de création de
processus durant le cours de son exécution. Le processus créateur est le processus parent, le
processus créé est le processus fils. Le fils peut, à son tour, créer des processus, donnant lieu à
un arbre de processus.
En général, un processus nécessitera certaines ressources (mémoire, fichiers, périphériques)
pour s’exécuter. Ces ressources peuvent être obtenues du parent.
Quand un processus crée un nouveau processus fils, 2 possibilités existent en ce qui concerne
le parent :
Le parent continue à tourner concurremment avec son ou ses enfants ;
Le parent reste bloqué jusqu’à ce que tous ses enfants aient terminé leur exécution.
De plus, il y a deux possibilités quant à l’espace mémoire où réside le nouveau processus
enfant :
Cet espace mémoire est le même (c’est un clone), et donc il partage le même code et
les mêmes variables que son parent ;
L’espace mémoire du processus enfant est écrasé par un nouveau programme, qui est
chargé après la création de l’enfant.
Comprendre l’exec et le fork
Sous Linux, les processus sont les composants actifs du système. Un programme chargé en
mémoire et son environnement forment un processus.
Le système de création de processus n'autorise que deux types d'opérations sur les processus :
la duplication d'un processus existant par la commande système fork; (c'est vrai pour tous les
processus)
le remplacement d'un programme dans un processus en cours par la commande système exec.
L’appel système fork crée un nouveau processus fils. Le processus fils a un nouveau PID
(identificateur de processus) et il partage son code et ses ressources avec son père.
Typiquement, un appel de type exec est utilisé juste après fork par le processus fils pour
écraser le code cloné du père par un nouveau programme. L’appel système execve vient donc
charger en mémoire une image binaire à partir d’un fichier, détruisant ainsi la copie dont le
fils avait hérité. Le PID du fils ne change pas.
Le père peut alors créer d’autres enfants (et rester prêt) ou attendre que son ou ses fils aient
terminé avec l’appel wait (il entre alors dans l’état bloqué).
Un processus se termine en général avec un appel à exit. Par convention, lorsqu’un processus
se termine sans problème, il passe la valeur 0 à exit, valeur que le père récupère bien souvent.
Toute autre valeur indique un problème.
Lorsqu’un utilisateur tente de se connecter au système, init crée un nouveau processus (PID
3), puis fait un exec qui remplace le code d’init par getty (un programme qui affiche une
invite de commande pour que l’utilisateur entre son login et mot de passe). getty fait un exec
pour devenir login (qui vérifie le mot de passe), qui lance un autre exec pour se faire écraser
par /bin/sh, le shell de l’utilisateur (bash, par exemple).
Dans notre exemple, l’utilisateur loggé entre la commande ls, ce qui fait que le shell fait
d’abord un fork, puis un exec pour lancer ls.
Quand la commande est terminée, le processus fils fait un exit et se termine, tout en
retournant une valeur d’état (0 ou autre chose) au parent, qui attendait avec wait.
Le fork
La coquille bash, notamment, utilise ces deux mécanismes pour l’exécution des commandes.
La création d’un processus connaît deux étapes : l’appel système fork() (ou parfois clone())
réalise une copie exacte, à quelques petites différences près, du processus parent. Une entrée
est créée par le noyau dans la table des processus pour cette copie, le fils. Le numéro du
processus-fils et le numéro du processus-père sont différents.
L’appel système fork crée un nouveau processus quasiment identique au processus père. Il
possède les mêmes droits (mêmes UID et GID) et exécute le même programme. Après l’appel
d’un (vreation d’un fils), il est possible de faire un appel à exec, selon l’une de ses syntaxes,
Leurs PCB (process control block) sont étrangement semblables…