Warum ist die Linux-Modul-API nicht abwärtskompatibel?
Warum ist die Linux-Modul-API nicht abwärtskompatibel? Ich bin frustriert, aktualisierte Treiber zu finden, nachdem ich den Linux-Kernel aktualisiert habe.
Ich habe einen drahtlosen Adapter, der einen proprietären Treiber benötigt, aber der Hersteller hat dieses Gerät vor etwa 7 Jahren eingestellt. Da der Code sehr alt ist und für Linux 2.6.0.0 geschrieben wurde, lässt er sich nicht mit den neuesten Linux-Kernels kompilieren. Ich habe viele Linux-Distributionen verwendet, aber das gleiche Problem ist überall. Obwohl es einen Open-Source-Treiber gibt, der mit dem Linux-Kernel verteilt wird, funktioniert er nicht. Einige Leute versuchen, den alten proprietären Code zu modifizieren, um ihn mit den neuesten Linux-Kerneln kompatibel zu machen, aber wenn ein neuer Linux-Kernel veröffentlicht wird, dauert es Monate, bis der Code damit kompatibel ist. Innerhalb dieser Zeit wird eine weitere neue Version veröffentlicht. Aus diesem Grund kann ich nicht auf einen neuen Linux-Kernel upgraden; Manchmal kann ich nicht einmal meine Distribution aktualisieren.
Antworten
Greg Kroah-Hartman hat zu diesem Thema hier geschrieben:https://www.kernel.org/doc/html/v4.10/process/stable-api-nonsense.html
Neben einigen technischen Details zum Kompilieren von C-Code skizziert er ein paar grundlegende Software-Engineering-Probleme, die ihre Entscheidung treffen.
Der Linux-Kernel ist immer in Arbeit. Dies geschieht aus vielen Gründen:
- Neue Anforderungen kommen hinzu. Die Leute wollen, dass ihre Software mehr kann, deshalb aktualisieren die meisten von uns, wir wollen die neuesten und besten Funktionen. Diese können eine Nacharbeit an der bestehenden Software erfordern.
- Es werden Fehler gefunden, die behoben werden müssen, manchmal liegen Fehler im Design selbst und können nicht ohne erhebliche Nacharbeit behoben werden
- Neue Ideen und Redewendungen in der Softwarewelt entstehen und die Leute finden viel einfachere / elegantere / effizientere Wege, Dinge zu tun.
Dies gilt für die meisten Softwareprogramme , und jede Software, die nicht gewartet wird, wird einen langsamen und schmerzhaften Tod sterben . Sie fragen sich, warum dieser alte, nicht gepflegte Code immer noch nicht funktioniert?
Warum werden alte Schnittstellen nicht gepflegt?
Um die Abwärtskompatibilität zu gewährleisten, müssten alte (oft „kaputte“ und unsichere) Schnittstellen beibehalten werden. Natürlich ist es theoretisch möglich, dies zu tun, außer es ist mit erheblichen Kosten verbunden .
Greg Kroah-Hartman schreibt
Wenn Linux sicherstellen müsste, dass es eine stabile Quellschnittstelle behält, wäre eine neue Schnittstelle erstellt worden, und die ältere, kaputte Schnittstelle hätte im Laufe der Zeit gewartet werden müssen, was zu zusätzlicher Arbeit für die [Entwickler] geführt hätte. Da alle Linux [Entwickler] ihre Arbeit in ihrer Freizeit erledigen, ist es keine Möglichkeit, Programmierer zu bitten, zusätzliche Arbeit ohne Gewinn und kostenlos zu leisten.
Obwohl Linux Open Source ist, bleibt nur begrenzt Entwicklerzeit, um es zu warten. Man kann also immer noch über "Kosten" diskutieren. Die Entwickler müssen wählen, wie sie ihre Zeit verbringen:
- Verbringen Sie viel Zeit damit, alte / defekte / langsame / unsichere Schnittstellen zu warten. Dies kann manchmal das Doppelte bis Dreifache der Zeit sein, die zum Schreiben der Schnittstelle in der ersten Instanz benötigt wurde.
- Werfen Sie die alten Schnittstellen weg und erwarten Sie von anderen Software-Betreuern, dass sie ihre eigene Software pflegen.
Alles in allem ist das Binning von Schnittstellen wirklich kostengünstig (für die Kernel-Entwickler) . Wenn Sie wissen wollen, warum Entwickler nicht Monate und Jahre ihres Lebens damit verbringen, Sie davor zu bewahren, 10 US-Dollar für einen neuen WLAN-Adapter zu bezahlen ... das ist der Grund. Denken Sie daran, dass dies für die Kernel-Entwickler zeit- und kosteneffizient ist, nicht unbedingt für Sie oder die Hersteller.
Obwohl ich einige (sehr kleine) Patches zum Linux-Kernel beigetragen habe, zähle ich mich nicht zu den Kernel-Entwicklern. Folgendes weiß ich jedoch:
Ein Treiber, der für die Kernel-Version 2.6.0.0 geschrieben wurde, geht auf die Eliminierung von Big Kernel Lock (BKL) zurück, die in der Kernel-Version 2.6.39 stattfand.
Die BKL wurde damals erstellt, als Linux noch ein Single-Prozessor-Betriebssystem (Single-Core, Single-Thread) war. Als die SMP-Unterstützung hinzukam, erkannten die Entwickler, dass die BKL irgendwann zu einem großen Flaschenhals werden würde, aber solange es nur wenige Kerne/Threads im System insgesamt gab, war es einigermaßen erträglich. Aber es wurde zuerst ein echtes Problem für Leute, die Linux in Supercomputern verwendeten, und so begann die Arbeit, alles, was die BKL benötigte, durch feinkörnigere Sperrmechanismen oder, wann immer möglich, durch sperrlose Methoden zu ersetzen.
Auf modernen Computern, die auf normalen Desktops und Hochleistungs-Laptops eine zweistellige Anzahl von Kernen haben können, ganz zu schweigen von Servern, müsste eine 2.6.0-abwärtskompatible Kernel-Modul-API auch BKL implementieren.
Wenn ein Legacy-Modul sagt "Ich möchte die BKL übernehmen", hat der Rest des Kernels keine Ahnung, was das Modul damit vorhat, und daher müsste der Abwärtskompatibilitätsmechanismus alle Sperren übernehmen, die die BKL ersetzt haben nur um alle Möglichkeiten abzudecken. Das wäre ein großer Performance-Hit. Und die neuen Lockless-Methoden müssten auch nach dem Legacy-Lock suchen – was den Punkt, überhaupt Lockless zu sein, zunichte macht. Die bloße Existenz des Abwärtskompatibilitätsmechanismus würde also die Systemleistung beeinträchtigen, selbst wenn keine Legacy-Module tatsächlich geladen würden.
In jüngerer Zeit haben die Spectre/Meltdown-Sicherheitspatches große Änderungen daran vorgenommen, was passieren muss, wenn die Kernel/Userspace-Grenze überschritten wird. Alle Module, die vor der Implementierung der Spectre/Meltdown-Fixes kompiliert wurden, können mit Post-Specre/Meltdown-Kerneln unzuverlässig sein.
Erst vor zwei Wochen habe ich Fehler bei einem alten Server behoben, der manuell aus- und wieder eingeschaltet werden musste, als Sicherheitsupdates automatisch angewendet wurden. Dies war schon mehrfach vorgekommen und reproduzierbar. Ich fand heraus, dass es eine sehr alte Version des proprietären megasrSpeichertreibers von vor den Spectre/Meltdown-Patches gab, die nicht in den automatischen Updates enthalten war. Nach Update des Treibers auf die aktuelle Version war das Problem weg. Übrigens war dies auf einem einfachen RHEL 6.10-System.
Ich habe auch Serverabstürze gesehen, wenn proprietäre Pre-Spectre/Meltdown-Hardwareüberwachungstreiber mit einem Post-Spectre/Meltdown-Kernel geladen wurden. Basierend auf dieser Erfahrung bin ich fest davon überzeugt, dass die Spectre/Meltdown-Fixes als Wendepunkt behandelt werden müssen: Der Kernel und die Module müssen entweder alle Before-Fixes- oder alle After-Fixes-Versionen sein; Mischen und Anpassen wird nur zu Kummer und Mitternachts-Weckrufen für den Bereitschafts-Systemadministrator führen.
Und da Spectre ein Problem auf CPU- Designebene war , ist es „ein Geschenk, das immer weitergibt“: Einige Leute werden neue Wege finden, um die Schwachstellen auszunutzen, und dann müssen die Kernel-Entwickler Wege finden, die Exploits zu blockieren.
Dies sind nur zwei der großen Probleme, die eine 2.6.0.0-kompatible Legacy-Kernel-Modul-API lösen müsste. Ich bin sicher, es gibt noch viele andere.
Und dann gibt es noch die eher philosophische Seite. Denken Sie darüber nach: Was macht Linux möglich?
Ein großer Teil davon sind offene Hardwarespezifikationen . Wenn die Hardwarespezifikationen offen sind, kann jeder teilnehmen. Da der Quellcode des Betriebssystems offen ist, kann jeder zum Nutzen aller beitragen. Und Sie können Hardwareprogrammierungsspezifikationen nicht als Ihr Geschäftsgeheimnis behalten, wenn Ihr Treibercode Open Source ist.
Linux-Kernel-Entwickler neigen dazu, an das Open-Source-Modell zu glauben. Aus diesem Grund haben sie ihre Design- und Entwicklungsentscheidungen so getroffen, dass der bevorzugte Weg für den Hardwarehersteller zur Teilnahme darin besteht, den Treiber als Open Source zu veröffentlichen, ihn in die Hauptkernel-Quelldistribution einzubinden, und dann (und nur dann ) werden Sie es tun Profitieren Sie von der gesamten Kernel-Entwicklergemeinschaft bei der Wartung.
Dies bietet einen gewissen Anreiz für Hardwaredesigner und -hersteller, dies zu ermöglichen. Wenn Sie etwas haben, das Sie geheim halten möchten, machen Sie sich die Mühe, es in einen ASIC zu kapseln, oder vielleicht in eine signierte Firmware, wenn Sie müssen. (Wenn Sie Letzteres tun, erteilen Sie anderen bitte die Erlaubnis, das Firmware-Paket weiterzuverteilen.)
Da der Kernel aber Open Source ist, können die Kernel-Entwickler nicht gerade verhindern , dass andere proprietäre Treiber separat pflegen. Aber sie haben auch keinen Anreiz, sich um sie zu kümmern.
Tatsächlich ist der zusätzliche Aufwand, der durch proprietäre Binärtreiber beim Kernel-Debugging verursacht wird, ein Anreiz für Kernel-Entwickler, sich nicht um die Entwicklung proprietärer Treiber zu kümmern: "Sie machen meine Arbeit schwieriger, warum sollte ich etwas Besonderes tun, um ihre Arbeit zu erleichtern?"
Die Kernel-Entwickler tun also im Allgemeinen das, was für sie als Gruppe/Gemeinschaft am vorteilhaftesten ist. Wenn das eine Modul-API-Änderung beinhaltet, sei es so. Die Treiber von Drittanbietern kommen nicht einmal in die Gleichung.