Ich fing an, über dieses Problem im Kontext der Etikette auf der Linux-Kernel-Mailingliste nachzudenken. Der Linux-Kernel ist das bekannteste und wohl erfolgreichste und wichtigste freie Software-Projekt der Welt. Und der Projektgründer und Leiter, Linus Torvalds, braucht hier eindeutig keine Einführung.
Linus zieht gelegentlich Kontroversen mit seinen Flammen auf dem LKML an. Diese Flammen haben, wie er selbst zugibt, häufig damit zu tun, den Benutzerraum zu durchbrechen. Was mich zu meiner Frage bringt.
Kann ich eine historische Perspektive haben, warum es so schlimm ist, den Benutzerraum zu knacken? Soweit ich weiß, sind für die Aufteilung des Benutzerraums Korrekturen auf Anwendungsebene erforderlich. Ist dies jedoch eine schlechte Sache, wenn der Kernelcode verbessert wird?
So wie ich es verstehe, besagt Linus 'erklärte Richtlinie, dass das Nicht-Brechen des Benutzerraums alles andere übertrumpft, einschließlich der Codequalität. Warum ist das so wichtig und was sind die Vor- und Nachteile einer solchen Politik?
(Eine solche, konsequent angewandte Politik hat eindeutig einige Nachteile, da Linus gelegentlich "Meinungsverschiedenheiten" mit seinen Top-Leutnants im LKML zu genau diesem Thema hat. Soweit ich das beurteilen kann, ist er in dieser Angelegenheit immer auf dem richtigen Weg.)
quelle
Antworten:
Der Grund ist kein historischer, sondern ein praktischer. Es gibt viele, viele Programme, die auf dem Linux-Kernel laufen. Wenn eine Kernel-Schnittstelle diese Programme beschädigt, müsste jeder diese Programme aktualisieren.
Nun ist es wahr, dass die meisten Programme tatsächlich nicht direkt von Kernel-Interfaces (den Systemaufrufen ) abhängen , sondern nur von Interfaces der C-Standardbibliothek (C- Wrapper um die Systemaufrufe). Oh, aber welche Standardbibliothek? Glibc? uClibC? Dietlibc? Bionic? Musl? etc.
Es gibt aber auch viele Programme, die betriebssystemspezifische Dienste implementieren und von Kernel-Schnittstellen abhängen, die von der Standardbibliothek nicht verfügbar gemacht werden. (Unter Linux werden viele davon über
/proc
und angeboten/sys
.)Und dann gibt es statisch kompilierte Binärdateien. Wenn ein Kernel-Upgrade einen dieser Fehler verursacht, besteht die einzige Lösung darin, sie erneut zu kompilieren. Wenn Sie die Quelle haben: Linux unterstützt auch proprietäre Software.
Selbst wenn die Quelle verfügbar ist, kann es schmerzhaft sein, alles zu sammeln. Vor allem, wenn Sie Ihren Kernel aktualisieren, um einen Fehler mit Ihrer Hardware zu beheben. Leute aktualisieren ihren Kernel oft unabhängig vom Rest ihres Systems, weil sie die Hardwareunterstützung benötigen. Mit den Worten von Linus Torvalds :
Er erklärt auch, dass ein Grund, dies zu einer strengen Regel zu machen, darin besteht, die Abhängigkeitshölle zu vermeiden, bei der Sie nicht nur ein anderes Programm aktualisieren müssen, um einen neueren Kernel zum Laufen zu bringen, sondern auch noch ein weiteres und ein weiteres Programm aktualisieren müssen , weil alles von einer bestimmten Version von allem abhängt.
Im Benutzerbereich werden diese gegenseitigen Abhängigkeiten normalerweise durch Beibehalten verschiedener Bibliotheksversionen aufgelöst. Sie dürfen jedoch nur einen Kernel ausführen, daher muss dieser alles unterstützen, was die Leute damit tun möchten.
offiziell ,
In der Praxis jedoch
Was sich jedoch häufiger ändert, sind Schnittstellen, die nur für hardwarebezogene Programme vorgesehen sind
/sys
. (/proc
Auf der anderen Seite, die seit der Einführung von/sys
nicht hardwarebezogenen Diensten so gut wie nie auf inkompatible Weise unterbrochen wurde.)Zusammenfassend,
und das ist schlecht, weil es nur einen Kernel gibt, den die Leute unabhängig vom Rest ihres Systems aktualisieren möchten, aber es gibt viele verschiedene Anwendungen mit komplexen Abhängigkeiten. Es ist einfacher, den Kernel stabil zu halten, als Tausende von Anwendungen in Millionen verschiedener Setups auf dem neuesten Stand zu halten.
quelle
In jedem voneinander abhängigen System gibt es grundsätzlich zwei Möglichkeiten. Abstraktion und Integration. (Ich verwende absichtlich keine Fachbegriffe). Mit Abstraction sagen Sie, dass beim Aufrufen einer API der Code hinter der API zwar geändert werden kann, das Ergebnis jedoch immer gleich ist. Wenn wir beispielsweise anrufen, ist
fs.open()
es uns egal, ob es sich um ein Netzwerklaufwerk, eine SSD oder eine Festplatte handelt, wir erhalten immer einen offenen Dateideskriptor, mit dem wir etwas anfangen können. Ziel von "Integration" ist es, die "beste" Möglichkeit zu bieten, etwas zu tun, auch wenn sich die Art und Weise ändert. Das Öffnen einer Datei kann beispielsweise für eine Netzwerkfreigabe anders sein als für eine Datei auf der Festplatte. Beide Möglichkeiten werden im modernen Linux-Desktop ziemlich häufig verwendet.Aus Entwicklersicht handelt es sich um "Arbeitet mit jeder Version" oder "Arbeitet mit einer bestimmten Version". Ein gutes Beispiel dafür ist OpenGL. Die meisten Spiele funktionieren mit einer bestimmten Version von OpenGL. Es spielt keine Rolle, ob Sie aus dem Quellcode kompilieren. Wenn das Spiel für OpenGL 1.1 geschrieben wurde und Sie versuchen, es auf 3.x laufen zu lassen, werden Sie keine gute Zeit haben. Am anderen Ende des Spektrums wird erwartet, dass einige Anrufe funktionieren, egal was passiert. Zum Beispiel möchte ich anrufen, ich möchte
fs.open()
mich nicht darum kümmern, auf welcher Kernel-Version ich bin. Ich möchte nur einen Dateideskriptor.Für jeden Weg gibt es Vorteile. Die Integration bietet "neuere" Funktionen auf Kosten der Abwärtskompatibilität. Während Abstraktion Stabilität gegenüber "neueren" Aufrufen bietet. Es ist wichtig zu wissen, dass dies Priorität hat und nicht die Möglichkeit.
Aus kommunaler Sicht ist Abstraktion in einem komplexen System ohne wirklich guten Grund immer besser. Stellen Sie sich zum Beispiel vor, Sie würden
fs.open()
je nach Kernel-Version unterschiedlich arbeiten. Dann müsste eine einfache Interaktionsbibliothek für das Dateisystem mehrere hundert verschiedene Methoden zum Öffnen von Dateien (oder wahrscheinlich Blöcke) verwalten. Wenn eine neue Kernel-Version herauskommt, können Sie nicht "upgraden", sondern müssen jede einzelne von Ihnen verwendete Software testen. Kernel 6.2.2 (Fake) kann Ihren Texteditor beschädigen.Für einige Beispiele aus der Praxis ist es OSX normalerweise egal, wie viel Speicherplatz für Benutzer zur Verfügung steht. Sie zielen häufiger auf "Integration" als auf "Abstraktion". Und bei jedem größeren Betriebssystem-Update geht es schief. Das heißt nicht, dass ein Weg besser ist als der andere. Es ist eine Wahl und Designentscheidung.
Am wichtigsten ist, dass das Linux-Ökosystem mit großartigen Open Source-Projekten gefüllt ist, in denen Menschen oder Gruppen in ihrer Freizeit an dem Projekt arbeiten oder weil das Tool nützlich ist. In diesem Sinne werden diese Entwickler in dem Moment, in dem es keinen Spaß mehr macht und anfängt, PIA zu werden, woanders hingehen.
Ich habe zum Beispiel einen Patch an gesendet
BuildNotify.py
. Nicht weil ich altruistisch bin, sondern weil ich das Tool benutze und eine Funktion wollte. Es war einfach, also hier einen Patch. Wenn es kompliziert oder umständlich wäre, würde ich es nicht benutzenBuildNotify.py
und ich würde etwas anderes finden. Wenn mein Texteditor bei jedem Kernel-Update kaputt gehen sollte, würde ich einfach ein anderes Betriebssystem verwenden. Meine Beiträge zur Community (so klein sie auch sein mögen) würden nicht weiter bestehen oder existieren und so weiter.Also wurde die Designentscheidung getroffen, um Systemaufrufe zu abstrahieren, so dass
fs.open()
es funktioniert , wenn ich es tue . Das bedeutet,fs.open
lange nachfs.open2()
der Popularität zu bleiben.Historisch ist dies das Ziel von POSIX-Systemen im Allgemeinen. "Hier finden Sie eine Reihe von Aufrufen und erwarteten Rückgabewerten, die Sie in der Mitte herausfinden." Wieder aus Gründen der Portabilität. Warum sich Linus für diese Methode entscheidet, hängt von seinem Gehirn ab, und Sie müssten ihn fragen, warum. Wenn ich es jedoch wäre, würde ich die Abstraktion der Integration in einem komplexen System vorziehen.
quelle
Es ist eine Designentscheidung und -wahl. Linus möchte Anwenderbereichsentwicklern garantieren können, dass Änderungen im Kernel, außer in äußerst seltenen und außergewöhnlichen (z. B. sicherheitsrelevanten) Fällen, ihre Anwendungen nicht beschädigen.
Die Profis sind, dass Userpace-Entwickler nicht finden werden, dass ihr Code aus willkürlichen und launischen Gründen plötzlich auf neuen Kernels bricht.
Die Nachteile sind, dass der Kernel alten Code und alte Systemaufrufe usw. für immer aufbewahren muss (oder zumindest längst über ihre Verfallsdaten hinaus).
quelle