Pourquoi existe-t-il une politique du noyau Linux pour ne jamais casser l'espace utilisateur?


38

J'ai commencé à réfléchir à cette question dans le contexte de l'étiquette sur la liste de diffusion Linux Kernel. En tant que projet de logiciel libre le plus connu et sans doute le plus réussi et le plus important au monde, le noyau Linux reçoit beaucoup de presse. Et le fondateur et chef de projet, Linus Torvalds, n'a clairement pas besoin d'être présenté ici.

Linus suscite parfois des controverses avec ses flammes sur le LKML. De son propre aveu, ces flammes ont souvent pour but de casser l’espace utilisateur. Ce qui m'amène à ma question.

Puis-je avoir une perspective historique sur la raison pour laquelle casser l’espace utilisateur est une si mauvaise chose? Si je comprends bien, casser l’espace utilisateur demanderait des corrections au niveau de l’application, mais est-ce une si mauvaise chose d’améliorer le code du noyau?

Si je comprends bien, la politique déclarée de Linus est que ne pas casser l’espace utilisateur prime sur tout le reste, y compris la qualité du code. Pourquoi est-ce si important et quels sont les avantages et les inconvénients d'une telle politique?

(Il y a clairement des inconvénients à une telle politique, appliquée systématiquement, étant donné que Linus a parfois des "désaccords" avec ses principaux lieutenants du LKML sur exactement ce sujet. Pour autant que je sache, il réussit toujours.)


1
Vous avez mal orthographié le nom de Linus dans l'introduction.
Ismael Miguel

Ce n’était pas de moi à coup sûr, mais j’ai oublié de voter et m’en suis allée maintenant.
Ismael Miguel

Réponses:


38

La raison n’est pas historique mais pratique. Il y a beaucoup de nombreux programmes qui s'exécutent sur le noyau Linux; Si une interface de noyau casse ces programmes, tout le monde devra les mettre à jour.

Il est vrai que la plupart des programmes ne dépendent pas directement des interfaces du noyau ( appels système ), mais uniquement des interfaces de la bibliothèque standard C ( enveloppeurs C autour des appels système). Oh, mais quelle bibliothèque standard? Glibc? uClibC? Dietlibc? Bionique? Musl? etc.

Cependant, de nombreux programmes implémentent des services spécifiques au système d'exploitation et dépendent d'interfaces du noyau qui ne sont pas exposées par la bibliothèque standard. (Sur Linux, beaucoup d’entre eux sont offerts par /procet /sys.)

Et puis il y a des binaires compilés statiquement. Si une mise à niveau du noyau casse l'un de ces problèmes, la seule solution serait de les recompiler. Si vous en avez la source: Linux prend également en charge les logiciels propriétaires.

Même lorsque la source est disponible, tout rassembler peut être une douleur. Surtout lorsque vous mettez à niveau votre noyau pour corriger un bogue avec votre matériel. Les gens mettent souvent à niveau leur noyau indépendamment du reste de leur système car ils ont besoin du support matériel. Dans les mots de Linus Torvalds :

Interrompre les programmes utilisateur n'est tout simplement pas acceptable. (…) Nous savons que les utilisateurs utilisent d'anciens fichiers binaires pendant des années et que faire une nouvelle version ne signifie pas que vous pouvez simplement le jeter. Vous pouvez nous faire confiance.

Il explique également que l’une des raisons pour faire de cette règle une règle stricte est d’éviter toute dépendance, car il vous faudrait non seulement mettre à niveau un autre programme pour que le nouveau noyau fonctionne, mais également mettre à niveau un autre programme, et un autre, et un autre. , parce que tout dépend d’une certaine version de tout.

C'est assez correct d'avoir une dépendance à sens unique bien définie. C'est triste, mais inévitable parfois. (…) Ce qui n'est PAS OK, c'est d'avoir une dépendance à double sens. Si le code HAL de l'espace utilisateur dépend d'un nouveau noyau, ce n'est pas grave, même si je suppose que les utilisateurs espèrent qu'il ne s'agira pas du "noyau de la semaine", mais plutôt d'un "noyau des derniers mois".

Mais si vous avez une dépendance à deux voies, vous êtes foutu. Cela signifie que vous devez effectuer la mise à niveau en mode verrouillé, et que cela N'EST PAS ACCEPTABLE. C'est horrible pour l'utilisateur, mais plus important encore, c'est horrible pour les développeurs, car cela signifie que vous ne pouvez pas dire "un bogue est arrivé" et faire des choses comme essayer de le réduire avec une bissection ou similaire.

En espace utilisateur, ces dépendances mutuelles sont généralement résolues en conservant différentes versions de bibliothèque. mais vous ne pouvez exécuter qu'un seul noyau, il doit donc prendre en charge tout ce que les gens peuvent vouloir en faire.

officiellement ,

La compatibilité en amont pour [appels système déclarés stables] sera garantie pendant au moins 2 ans.

En pratique cependant,

La plupart des interfaces (comme les appels système) ne devraient jamais changer et rester disponibles.

Ce qui change le plus souvent, ce sont les interfaces destinées uniquement aux programmes liés au matériel, en format /sys. ( /procen revanche, qui depuis l'introduction de /sysa été réservé aux services non liés au matériel, ne se casse presque jamais de manière incompatible.)

En résumé,

briser l'espace utilisateur nécessiterait des corrections au niveau de l'application

Et c'est dommage car il n'y a qu'un seul noyau que les utilisateurs souhaitent mettre à niveau indépendamment du reste de leur système, mais il existe de nombreuses applications aux interdépendances complexes. Il est plus facile de garder le noyau stable que de garder des milliers d'applications à jour sur des millions de configurations différentes.


1
Merci pour la réponse. Donc, les interfaces déclarées stables sont un sur-ensemble des appels système POSIX? Ma question sur l'histoire est de savoir comment cette pratique a évolué. Vraisemblablement, les versions originales du noyau Linux ne s'inquiétaient pas de la rupture de l'espace utilisateur, du moins au début.
Faheem Mitha

3
@FaheemMitha Oui, ils l'ont fait depuis 1991 . Je ne pense pas que l'approche de Linus ait évolué, cela a toujours été «les interfaces pour les applications normales ne changent pas, les interfaces pour les logiciels très fortement liés au noyau changent très très rarement».
Gilles, arrête de faire le mal '12

24

Dans tous les systèmes interdépendants, il existe essentiellement deux choix. Abstraction et intégration. (Je n'utilise pas volontairement des termes techniques) Avec Abstraction, vous dites que lorsque vous appelez une API, le résultat sera toujours le même, même si le code derrière l'API peut changer. Par exemple, lorsque nous appelons fs.open(), peu importe qu'il s'agisse d'un lecteur réseau, d'un SSD ou d'un disque dur, nous obtiendrons toujours un descripteur de fichier ouvert avec lequel nous pourrons travailler. Avec "intégration", l’objectif est de fournir le "meilleur" moyen de faire une chose, même si la façon de le faire change. Par exemple, l'ouverture d'un fichier peut être différente pour un partage réseau et pour un fichier sur disque. Les deux méthodes sont assez utilisées dans le bureau Linux moderne.

Du point de vue des développeurs, il s’agit de "fonctionne avec n’importe quelle version" ou "fonctionne avec une version spécifique". OpenGL est un bon exemple de cela. La plupart des jeux sont configurés pour fonctionner avec une version spécifique d'OpenGL. Peu importe si vous compilez à partir des sources. Si le jeu a été écrit pour utiliser OpenGL 1.1 et que vous essayez de le faire tourner sous 3.x, vous n’allez pas passer un bon moment. À l’autre bout du spectre, certains appels devraient fonctionner de toute façon. Par exemple, je veux appeler fs.open()je ne veux pas me soucier de la version de mon noyau. Je veux juste un descripteur de fichier.

Il y a des avantages dans chaque sens. L'intégration fournit des fonctionnalités "plus récentes" au détriment de la compatibilité ascendante. Tandis que l’abstraction offre une stabilité par rapport aux appels "plus récents". Bien qu'il soit important de noter que c'est une question de priorité, pas de possibilité.

D'un point de vue commun, sans une très bonne raison, l'abstraction est toujours préférable dans un système complexe. Par exemple, imaginez si vous fs.open()travaillez différemment selon la version du noyau. Ensuite, une simple bibliothèque d’interaction avec le système de fichiers doit gérer plusieurs centaines de méthodes de "fichiers ouverts" (ou de blocs). Quand une nouvelle version du noyau est sortie, vous ne pouvez pas "mettre à jour", vous devez tester chaque logiciel que vous utilisez. Le noyau 6.2.2 (faux) peut juste casser votre éditeur de texte.

Pour certains exemples concrets, OSX a tendance à ne pas se soucier de casser l’espace utilisateur. Ils visent plus fréquemment «l'intégration» à «l'abstraction». Et à chaque mise à jour majeure du système d'exploitation, les choses se cassent. Cela ne veut pas dire qu'une façon est meilleure que l'autre. C'est un choix et une décision de conception.

Plus important encore, l'écosystème Linux regorge de projets Open Source impressionnants, dans lesquels des personnes ou des groupes travaillent sur le projet pendant leur temps libre ou parce que l'outil est utile. En gardant cela à l’esprit, à la seconde où cela cesse d’être amusant et commence à être une PIA, ces développeurs iront ailleurs.

Par exemple, j'ai soumis un correctif à BuildNotify.py. Non pas parce que je suis altruiste, mais parce que j'utilise l'outil et que je voulais une fonctionnalité. C'était facile, alors voici un patch. Si c'était compliqué ou lourd, je ne l'utiliserais pas BuildNotify.pyet je trouverais autre chose. Si chaque fois qu'une mise à jour du noyau était publiée, mon éditeur de texte tombait en panne, j'utiliserais simplement un système d'exploitation différent. Mes contributions à la communauté (si petites soient-elles) ne continueraient pas ou n'existeraient pas, etc.

Ainsi, la conception a été prise pour des appels système abstraits, de sorte que lorsque je le fais, fs.open()cela fonctionne. Cela signifie maintenir fs.openlongtemps après avoir fs.open2()gagné en popularité.

Historiquement, c'est l'objectif des systèmes POSIX en général. "Voici un ensemble d'appels et les valeurs de retour attendues, vous déterminez le milieu." Encore une fois pour des raisons de portabilité. Pourquoi Linus a choisi d'utiliser cette méthodologie est interne à son cerveau, et vous devrez lui demander de savoir exactement pourquoi. Si c’était moi cependant, je choisirais l’abstraction sur l’intégration sur un système complexe.


1
L'API vers l'espace utilisateur, l'API 'syscall', est bien définie (en particulier le sous-ensemble POSIX) et stable, car la suppression de toute partie de celle-ci endommagerait les logiciels éventuellement installés. Ce qu'il n'a pas, c'est une API de pilote stable .
pjc50

4
@FaheemMitha, c'est l'inverse. Les développeurs du noyau sont libres de casser l’API du pilote quand ils le souhaitent, à condition de corriger tous les pilotes dans le noyau avant la prochaine version. C'est casser l'API de l'espace utilisateur, ou même faire des choses non-API qui pourraient le casser, qui produit des réactions épiques de Linus.
Marc

4
Par exemple, si quelqu'un décide de le changer en renvoyant un code d'erreur différent de ioctl () dans certaines circonstances: lkml.org/lkml/2012/12/23/75 (contient des attaques jurées et personnelles contre le développeur responsable). Ce correctif a été rejeté car cela aurait cassé PulseAudio, et donc tout l'audio sur les systèmes GNOME.
pjc50

1
@FaheemMitha, fondamentalement, def add (a, b); retourne a + b; end --- def add (a, b); c = a + b; retourne c; end --- def add (a, b); c = a + b + 10; retournez c-10; end - sont tous la "même" implémentation de add. Ce qui le contrarie tellement, c’est quand les gens ne le font pas ajouter (a, b); return (a + b) * -1; end Essentiellement, il est correct de modifier le fonctionnement "interne" du travail du noyau. Changer ce qui est retourné à un appel d'API défini et "public" ne l'est pas. Il existe deux types d'appels d'API "privé" et "public". Il estime que les appels d'API publics ne devraient jamais changer sans bonne raison.
coteyr

3
Un exemple non-code; Vous allez au magasin, vous achetez du gaz à 87 octanes. En tant que consommateur, vous ne vous souciez pas de la provenance ou de la transformation du gaz. Vous vous souciez juste de votre essence. Si le gaz a subi un processus de raffinage différent, vous vous en fichez. Bien sûr, le processus de raffinage peut changer. Il y a même différentes sources de pétrole. Mais ce qui compte pour vous, c’est d’obtenir le 87 Octane. Donc, sa position est de changer les sources, de changer les raffineries, de changer quoi que ce soit, tant que la pompe produit le gaz 87 Octane. Tous les trucs "dans les coulisses" n'ont pas d'importance. Tant qu'il y a 87 octanes.
coteyr

8

C'est une décision de conception et de choix. Linus veut pouvoir garantir aux développeurs d’espace utilisateur que, sauf circonstances extrêmement rares et exceptionnelles (liées à la sécurité, par exemple), les modifications apportées au noyau ne casseront pas leurs applications.

Les pros sont que les développeurs en espace utilisateur ne verront pas leur code déferler brusquement sur de nouveaux noyaux pour des raisons arbitraires et capricieuses.

Les inconvénients sont que le noyau doit conserver l'ancien code et les anciens appels système, etc., pour toujours (ou, du moins, longtemps après leur date de péremption).


Merci pour la réponse. Êtes-vous au courant de l'évolution de cette décision? Je suis au courant de projets qui adoptent une perspective quelque peu différente. Par exemple, le projet Mercurial ne possède pas d’API fixe et peut casser le code qui en dépend.
Faheem Mitha

Non, désolé, je ne me souviens pas comment cela s'est passé. Vous pouvez envoyer un courrier électronique à Linus ou à LKML et lui demander.
cas

2
Mercurial n'est pas un système d'exploitation. L’intérêt d’un système d’exploitation est de permettre l’exécution d’autres logiciels, et casser cet autre logiciel est très impopulaire. En comparaison, Windows a également maintenu une compatibilité ascendante pendant très longtemps; Le code Windows 16 bits n’a été que récemment obsolète.
pjc50

@ pjc50 Certes, Mercurial n'est pas un système d'exploitation, mais il existe d' autres logiciels, même s'il ne s'agit que de scripts, qui en dépendent. Et peut potentiellement être brisé par des changements.
Faheem Mitha
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.