Il existe toutes sortes de noyaux, plus ou moins spécialisés. Des noyaux spécifiques à une architecture, souvent monotâches, d’autres généralistes et souvent multitâches et multiutilisateurs. L’ensemble de ces noyaux peut être divisé en deux approches opposées d’architectures logicielles : les noyaux monolithiques et les micro-noyaux.
On considère généralement les noyaux monolithiques, de conception ancienne, comme obsolètes car difficiles à maintenir et moins « propres ». Le noyau Linux était déjà qualifié d’obsolète par Andrew Tanenbaum, dès sa création en 1991. Il ne croyait pas, à l’époque, pouvoir faire un noyau monolithique multiplate-forme et modulaire. La mise en place de micro-noyaux, qui consiste à déplacer l’essentiel des fonctions du noyau vers l’espace utilisateur, est très intéressante en théorie mais s’avère difficile en pratique. Ainsi les performances du noyau Linux (monolithique) sont supérieures à celles de ses concurrents (noyaux généralistes à micro-noyaux), sans compter qu’il fut finalement porté sur de très nombreuses plates-formes et qu’il est modulaire depuis 1995.
Pour ces raisons de performance, les systèmes généralistes basés sur une technologie à micro-noyau, tels que Windows et Mac OS X, n’ont pas un « vrai » micro-noyau enrichi. Ils utilisent un micro-noyau hybride : certaines fonctionnalités qui devraient exister sous forme de mini-serveurs se retrouvent intégrées dans leur micro-noyau, utilisant le même espace d’adressage. Pour Mac OS X, cela forme XNU : le noyau monolithique BSD fonctionne en tant que service de Mach et ce dernier inclut du code BSD dans son propre espace d’adressage afin de réduire les latences.
Ainsi, les deux approches d’architectures de noyaux, les micro-noyaux et les noyaux monolithiques, considérées comme diamétralement différentes en termes de conception, se rejoignent quasiment en pratique par les micro-noyaux hybrides et les noyaux monolithiques modulaires.
Certains systèmes d’exploitation, comme d’anciennes versions de Linux, certains BSD ou certains vieux Unix ont un noyau monolithique. C’est-à-dire que l’ensemble des fonctions du système et des pilotes sont regroupés dans un seul bloc de code et un seul bloc binaire généré à la compilation.
De par la simplicité de leur concept mais également de leur excellente vitesse d’exécution, les noyaux monolithiques ont été les premiers à être développés et mis en œuvre. Cependant, au fur et à mesure de leurs développements, le code de ces noyaux monolithiques a augmenté en taille et il s’est avéré difficile de les maintenir. Le support par les architectures monolithiques des chargements à chaud ou dynamiques implique une augmentation du nombre de pilotes matériels compilés dans le noyau, et par suite, une augmentation de la taille de l’empreinte mémoire des noyaux. Celle-ci devint rapidement inacceptable. Les multiples dépendances créées entre les différentes fonctions du noyau empêchaient la relecture et la compréhension du code. L’évolution du code s’est faite en parallèle à l’évolution du matériel, et des problèmes de portage ont alors été mis en évidence sur les noyaux monolithiques.
En réalité les problèmes de la portabilité de code se sont révélés avec le temps indépendants de la problématique de la technologie des noyaux. Pour preuve, NetBSD est un noyau monolithique et est porté sur un très grand nombre d’architectures, alors que des noyaux tels que HURD ou celui de Windows XP utilisent des micro-noyaux censés faciliter le portage mais n’existent que pour quelques architectures.
Pour répondre aux problèmes des noyaux monolithiques, ces derniers sont devenus modulaires. Dans ce type de noyau, seules les parties fondamentales du système sont regroupées dans un bloc de code unique (monolithique). Les autres fonctions, comme les pilotes matériels, sont regroupées en différents modules qui peuvent être séparés tant du point de vue du code que du point de vue binaire.
La très grande majorité des systèmes actuels utilise cette technologie : Linux, la plupart des BSD ou Solaris. Par exemple avec le noyau Linux, certaines parties peuvent être non compilées ou compilées en tant que modules chargeables directement dans le noyau. La modularité du noyau permet le chargement à la demande de fonctionnalités et augmente les possibilités de configuration. Ainsi les systèmes de fichiers peuvent être chargés de manière indépendante, un pilote de périphérique changé, etc. Les distributions Linux, par exemple, tirent profit des modules chargeables lors de l’installation. L’ensemble des pilotes matériels sont compilés en tant que modules. Le noyau peut alors supporter l’immense variété de matériel trouvé dans les compatibles PC. Après l’installation, lors du démarrage du système, seuls les pilotes correspondants au matériel effectivement présent dans la machine sont chargés en mémoire vive. La mémoire est économisée.
Les noyaux monolithiques modulaires conservent les principaux atouts des noyaux monolithiques purs dont ils sont issus. Ainsi, la facilité de conception et de développement est globalement maintenue et la vitesse d’exécution reste excellente. L’utilisation de modules implique le découpage du code source du noyau en blocs indépendants. Ces blocs améliorent l’organisation et la clarté du code source et en facilitent également la maintenance.
Les noyaux monolithiques modulaires conservent également un important défaut des noyaux monolithiques purs : une erreur dans un module met en danger la stabilité de tout le système. Les tests et certifications de ces composants doivent être plus poussés.
D’un point de vue théorique, le grand nombre de lignes de code exécutées en mode noyau engendre des problèmes de portabilité. La pratique contredit largement la théorie et les noyaux modulaires sont aujourd’hui les plus portés.
Les limitations des noyaux monolithiques ont amené à une approche radicalement différente de la notion de noyau : les systèmes à micro-noyaux.
Les systèmes à micro-noyaux cherchent à minimiser les fonctionnalités dépendantes du noyau en plaçant la plus grande partie des services du système d’exploitation à l’extérieur de ce noyau, c’est-à-dire dans l’espace utilisateur. Ces fonctionnalités sont alors fournies par de petits serveurs indépendants possédant souvent leur propre espace d’adressage.
Un petit nombre de fonctions fondamentales est conservé dans un noyau minimaliste appelé « micro-noyau ». L’ensemble des fonctionnalités habituellement proposées par les noyaux monolithiques est alors assuré par les services déplacés en espace utilisateur et par ce micro-noyau. Cet ensemble logiciel est appelé « micro-noyau enrichi ».
Ce principe a de grands avantages théoriques : en éloignant les services « à risque » des parties critiques du système d’exploitation regroupées dans le noyau, il permet de gagner en robustesse et en fiabilité, tout en facilitant la maintenance et l’évolutivité. En revanche, les mécanismes de communication (IPC), qui deviennent fondamentaux pour assurer le passage de messages entre les serveurs, sont très lourds et peuvent limiter les performances.
Les avantages théoriques des systèmes à micro-noyaux sont la conséquence de l’utilisation du mode protégé par les services qui accompagnent le micro-noyau. En effet, en plaçant les services dans l’espace utilisateur, ceux-ci bénéficient de la protection de la mémoire. La stabilité de l’ensemble en est améliorée : une erreur d’un service en mode protégé a peu de conséquences sur la stabilité de l’ensemble de la machine.
De plus, en réduisant les possibilités pour les services de pouvoir intervenir directement sur le matériel, la sécurité du système est renforcée. Le système gagne également en possibilités de configuration. Ainsi, seuls les services utiles doivent être réellement lancés au démarrage. Les interdépendances entre les différents serveurs sont faibles. L’ajout ou le retrait d’un service ne perturbe pas l’ensemble du système. La complexité de l’ensemble est réduite.
Le développement d’un système à micro-noyau se trouve également simplifié en tirant parti à la fois de la protection de la mémoire et de la faible interdépendance entre les services. Les erreurs provoquées par les applications en mode utilisateur sont traitées plus simplement que dans le mode noyau et ne mettent pas en péril la stabilité globale du système. L’intervention sur une fonctionnalité défectueuse consiste à arrêter l’ancien service puis à lancer le nouveau, sans devoir redémarrer toute la machine.
Les micro-noyaux ont un autre avantage : ils sont beaucoup plus compacts que les noyaux monolithiques. 6 millions de lignes de code pour le noyau Linux 2.6.0 contre en général moins de 50 000 lignes pour les micro-noyaux. La maintenance du code exécuté en mode noyau est donc simplifiée. Le nombre réduit de lignes de code peut augmenter la portabilité du système.
Les premiers micro-noyaux (comme Mach) n’ont pas tout de suite atteint ces avantages théoriques. L’utilisation de nombreux services dans l’espace utilisateur engendre les deux problèmes suivants :
Le grand nombre d’appels système et la communication sous-jacente sont un défaut inhérent à la conception des micro-noyaux. Dans L4, il a été résolu en plaçant encore plus de services en espace utilisateur. La rapidité de traitement des IPC a pu être améliorée en simplifiant les communications au maximum, par exemple en supprimant toute vérification des permissions, laissant ce soin aux serveurs externes.
Ces modifications radicales ont permis d’obtenir de bonnes performances mais elles ne doivent pas faire oublier qu’un micro-noyau doit être accompagné d’un grand nombre de services pour fournir des fonctionnalités équivalentes à celles des noyaux monolithiques. De plus, la grande liberté dont disposent les services au niveau de la sécurité et de la gestion de la mémoire accroît la difficulté et le temps de leur développement (ils doivent fournir leurs propres interfaces).
Micro-noyau | Micro-noyau enrichi | Systèmes d’exploitation associés |
---|---|---|
L4 | HURD | GNU/HURD |
Mach (GNU Mach) | HURD | GNU/HURD |
Mach | XNU | Darwin |
Mach | XNU | Mac OS X |
La dénomination de « noyaux hybrides » désigne principalement des noyaux qui reprennent des concepts à la fois des noyaux monolithiques et des micro-noyaux, pour combiner les avantages des deux.
Lorsqu’au début des années 1990 les développeurs et concepteurs se sont aperçus des faiblesses des premiers micro-noyaux, certains réintégrèrent diverses fonctionnalités non fondamentales dans le noyau, pour gagner en performance. Les micro-noyaux « purs » semblaient condamnés à l’échec.
Alors que la philosophie générale des systèmes à micro-noyaux est maintenue (seules les fonctions fondamentales sont dans l’espace noyau), certaines fonctions non critiques, mais très génératrices d’appels système, sont réintégrées dans l’espace noyau. Ce compromis permet d’améliorer considérablement les performances en conservant de nombreuses propriétés des systèmes à micro-noyaux. Un exemple de ce type de noyau hybride est le noyau XNU de Mac OS X. Il est basé sur le micro-noyau Mach 3.0 mais qui inclut du code du noyau monolithique BSD au sein de l’espace noyau.
Cette dénomination est également utilisée pour désigner d’autres types de noyaux, notamment les noyaux monolithiques sur micro-noyaux (temps réel ou non) tels que L4Linux (Linux sur L4), MkLinux (le noyau Linux sur Mach), Adeos, RTLinux et RTAI.
Plus rarement, on peut rencontrer le terme « noyau hybride » pour remplacer improprement « noyau monolithique modulaire » ou « micro-noyau enrichi ».
Étymologiquement, 'exo' signifie en grec 'hors de'. Un exo-noyau est donc un système d'exploitation fonctionnant en espace utilisateur (en 'user-space', au lieu du 'kernel-space' dans le cas des autres noyaux). Les fonctions et services du système d'exploitation sont assurés par de petits modules qui, selon les approches techniques, sont des librairies dynamiques (MIT, LibOSes) ou des démons (IntraServices).
Un « méta-noyau » est un ensemble de logiciels qui vise à appliquer la notion de noyau informatique au niveau d’un réseau informatique, en créant une unique couche de gestion des périphériques au niveau d’un réseau.
De cette manière, les logiciels peuvent être déployés et utilisés sur le réseau informatique comme s’il s’agissait d’une machine unique, et l’ensemble des logiciels fonctionnant sur cette plate-forme peuvent se partager les ressources de manière intégrée, comme elle le ferait sur un noyau simple.
Un méta système doit également permettre la personnalisation, la gestion des permissions ainsi que l’utilisation d’informations dépendant de la localisation.
Cette notion rejoint les notions de grappe de calcul, de machine virtuelle, de serveur d’application et de CORBA.