Espace noyau et espace utilisateur

Avec un noyau monolithique comme celui de Linux, il est important de faire très attention lors de l'introduction de nouveau code et de nouvelles fonctionnalités. Ces décisions peuvent ensuite affecter de nombreuses choses dans le cycle de développement, au delà du noyau lui-même.

La première règle simple est d'éviter les interfaces. Si quelqu'un veut ajouter quelque chose qui implique une nouvelle interface système, vous devez être exceptionnellement attentif. Dès lors que vous fournissez une interface aux utilisateurs, ils vont commencer à l'utiliser et lorsque quelqu'un aura commencé à coder par dessus cette interface, vous ne pourrez plus vous en débarrasser. Voulez-vous maintenir exactement la même interface pour le reste de la vie de votre système ?

Le reste du code n'est pas si problématique. S'il n'a pas d'interface, par exemple un pilote de disque, alors il n'y a pas besoin d'y réfléchir longtemps  ; vous pouvez sans grand risque l'ajouter simplement. Si Linux n'avait pas ce pilote auparavant, l'ajouter ne gênera pas les utilisateurs antérieurs, et cela l'ouvre à de nouveaux utilisateurs.

Quand la question se pose sur d'autres plans, vous devez faire des compromis. Est-ce une bonne implémentation ? Est-ce que cela ajoute vraiment une intéressante fonctionnalité ? Parfois, même si la fonctionnalité est bonne, il se trouve que soit l'interface est mauvaise, soit l'implémentation est telle que vous ne pourrez jamais faire autre chose, maintenant ou plus tard.

Par exemple — bien que ce soit en quelque sorte une question d'interface  —  supposez que quelqu'un a une implémentation stupide d'un système de fichiers où les noms ne peuvent pas avoir plus de 14 caractères. Ce que vous voulez vraiment éviter est d'avoir, pour une interface, ces limitations gravées dans le marbre. Sinon, lorsque vous voudrez étendre le système de fichiers, vous serez foutu car devrez trouver une manière de rester dans cette petite interface jusqu'alors figée. Pire que cela, tout programme qui demande un nom de fichier peut avoir réservé (par exemple) 13 caractères pour une variable et ainsi, si vous passez un nom de fichier plus long, vous le planterez.

À présent, le seul éditeur qui fasse une chose aussi stupide est Microsoft. En simplifiant, pour lire des fichiers MS-DOS/MS-Windows, vous avez cette ridicule interface où les noms de fichiers comptent onze caractères, huit plus trois. Avec NT, qui a permis les noms longs, ils ont dû ajouter un ensemble complet de nouvelles routines pour faire la même chose que les anciennes, sauf que cet ensemble pouvait aussi prendre en compte de plus grands noms de fichiers. Cela constitue par là-même un exemple d'interface incorrecte car gênante lors des travaux ultérieurs.

Un autre exemple de cette situation est donné dans le système d'exploitation Plan 9. Ils avaient cet appel système vraiment pratique pour faire une meilleure duplication des processus. En deux mots, ce nouveau fork, appelé par Plan 9 R-Fork (et que SGI a appelé plus tard S-Proc) crée deux espaces d'exécution distincts partageant le même espace d'adressage. Cela facilite en particulier le threading.

Linux permet aussi cela avec son appel système « clone », mais il a été implémenté de façon correcte. Les concepteurs des routines SGI et Plan9 ont décidé que les programmes ayant deux branchements pouvaient partager le même espace d'adressage, mais séparèrent leurs piles. Normalement, lorsque vous utilisez la même adresse dans les deux threads, vous obtenez la même position mémoire. Mais le segment de pile est spécifique de sorte que si vous utilisez une adresse mémoire de la pile, vous obtenez en fait deux positions mémoires différentes, qui peuvent partager un pointeur de pile sans écraser l'autre pile. <-- incohérent (?) -->

Ce comportement est astucieux, mais a son revers : le surcoût de la maintenance des piles le rend, en pratique, vraiment inadéquat. Ils se sont aussi aperçus trop tard que les performances s'avèrent catastrophiques. Comme des programmes utilisaient cette interface, il n'y avait plus moyen de la modifier. Il leur a fallu introduire une interface supplémentaire, correctement écrite, de façon à utiliser l'espace de pile d'une façon raisonnable.

Un éditeur commercial peut de temps en temps essayer de faire passer le défaut de conception dans l'architecture mais Linux n'offre pas ce recours.

La gestion du développement de Linux et la prise de décisions de conception imposent la même approche. D'un point de vue pratique, je ne pouvais gérer le fait que de nombreuses personnes fournissent des interfaces au noyau. Je n'aurais pas été capable d'en garder le contrôle. Mais du point de vue conception, c'était aussi ce qu'il fallait faire : garder le noyau relativement petit et maintenir au minimum le nombre des interfaces et des autres contraintes imposées au développement futur.

Bien entendu, Linux n'est pas complètement « propre » de ce point de vue. Il a hérité des versions précédentes d'Unix un certain nombre d'interfaces affreuses. Ainsi, dans certains cas, j'aurais été bien plus heureux de ne pas avoir à maintenir la même interface qu'Unix. Mais Linux est à peu près aussi propre que peut l'être un système sans repartir complètement de zéro. Et si vous voulez profiter de la possibilité de faire fonctionner des applications Unix, il faut bien en accepter certaines lourdeurs. La possibilité de faire fonctionner ces applications a joué un rôle primordial dans la popularité de Linux, le jeu en valait donc la chandelle.