berühmte Ermahnung von Linus TorvaldsLCTT-Übersetzung: Gestern sagte AlmaLinux, dass es die 1:1-Kompatibilität mit RHEL „aufgeben“ würde, aber die ABI-Kompatibilität mit RHEL beibehalten würde, sodass auf RHEL laufende Software nahtlos auf AlmaLinux laufen kann. Einige Schüler sind sich möglicherweise nicht ganz im Klaren über das Konzept des ABI, daher habe ich diesen Artikel übersetzt, damit jeder ihn versteht.
Viele Linux-Enthusiasten kennen die
: „Wir zerstören den Benutzerraum nicht“, aber ihre Bedeutung ist möglicherweise nicht jedem klar, der sie hört. Diese „Erste Regel“ erinnert Entwickler an die Stabilität des Application Binary Interface (ABI), das für die Kommunikation und Konfiguration zwischen Anwendungen und dem Kernel verwendet wird. Das Folgende soll den Leser mit ABI-Konzepten vertraut machen, erklären, warum ABI-Stabilität wichtig ist, und diskutieren, was in einem stabilen Linux-ABI enthalten ist. Das kontinuierliche Wachstum und die Weiterentwicklung von Linux erforderten Änderungen am ABI, von denen einige umstritten waren.
Was ist ABI?
als API betrachtet. Programme, die die Bibliothek aufrufen oder Daten im String-Format austauschen, müssen sich an die in der API beschriebenen Konventionen halten, andernfalls kann es zu unerwarteten Ergebnissen kommen. ABIs ähneln APIs darin, dass sie festlegen, wie Befehle interpretiert und Binärdaten ausgetauscht werden. Für C-Programme umfasst der ABI typischerweise den Rückgabetyp und die Argumentliste von Funktionen, das Layout von Strukturen sowie die Bedeutung, Reihenfolge und den Umfang der Aufzählungstypen. Ab 2022 besteht der Linux-Kernel immer noch fast ausschließlich aus C-Programmen und muss sich daher an diese Spezifikationen halten.
Die Beschreibung von „
Kernel System Call Interface“ finden Sie im „Linux Manual Section 2“ und enthält etwas wie „), das von einer Middleware-Anwendung aufgerufen werden kann. Tatsächlich offiziell Das Linux ABI Die Dokumentation mount
和 sync
的 C 版本函数。这些函数的二进制布局是 Linux ABI 的第一个重要组成部分。对于问题 “Linux 的稳定 ABI 包括哪些内容?”,许多用户和开发人员的回答是 “sysfs(/sys
)和 procfs(/proc
konzentriert sich hauptsächlich auf diese virtuellen Dateisysteme Der vorherige Abschnitt konzentriert sich auf die Verwendung des Linux-ABI in Programmen, behandelt jedoch nicht die ebenso wichtigen menschlichen Faktoren der ABI-Funktionsanforderungen. Die Kernel-Community, C-Compiler (wie GCC
clang), Entwickler, die Userspace-C-Bibliotheken erstellen (normalerweise glibc) und Binäranwendungen im Executable and Linking Format (ELF). Kollaborative Bemühungen innerhalb der
Entwicklungsgemeinschaft.
Die Stabilitätsgarantie des Linux ABI von Torvalds selbst ermöglicht es Linux-Distributionen und einzelnen Benutzern, den Kernel selbstständig zu aktualisieren, ohne vom Betriebssystem beeinträchtigt zu werden.
Wenn Linux kein stabiles ABI hätte, müssten die meisten oder sogar das gesamte Betriebssystem jedes Mal neu installiert werden, wenn der Kernel gepatcht werden müsste, um ein Sicherheitsproblem zu beheben. Die Stabilität der Binärschnittstelle ist eindeutig einer der wichtigen Faktoren für die Benutzerfreundlichkeit und weite Verbreitung von Linux.
Terminalausgabe
Wie im Bild oben gezeigt, ist der Kernel (in linux-libc-dev
) und Glibc (in libc6-dev
) Bitmaske. Offensichtlich müssen diese beiden Definitionssätze übereinstimmen! apt
Der Paketmanager identifiziert jede vom Paket bereitgestellte Datei. Potenziell instabile Teile der Glibc-ABI befinden sich in bits/
Verzeichnis. linux-libc-dev
中)和 Glibc(在 libc6-dev
中)都提供了定义文件权限的位掩码。显然,这两个定义集必须一致!apt
软件包管理器会识别软件包提供每个文件。Glibc ABI 的潜在不稳定部分位于 bits/
目录中。
在大部分情况下,Linux ABI 的稳定性保证运作良好。按照 康韦定律Conway's Law,在开发过程中出现的烦人技术问题往往是由于不同软件开发社区之间的误解或分歧所致,而这些社区都为 Linux 做出了贡献。不同社区之间的接口可以通过 Linux 包管理器的元数据轻松地进行想象,如上图所示。
通过考虑当前正在进行的、缓慢发生 的 “Y2038” ABI 破坏的例子,可以更好地理解 Linux ABI。在 2038 年 1 月,32 位时间计数器将回滚到全零,就像较旧车辆的里程表一样。2038 年 1 月听起来还很遥远,但可以肯定的是,如今销售的许多物联网设备仍将处于运行状态。像今年安装的 智能电表 和 智能停车系统 这样的普通产品可能采用的是 32 位处理器架构,而且也可能不支持软件更新。
Linux 内核已经在内部转向使用 64 位的 time_t
不透明数据类型来表示更晚的时间点。这意味着像 time()
这样的系统调用在 64 位系统上已经变更了它们的函数签名。这些努力的艰难程度可以在内核头文件中(例如 time_types.h)清楚地看到,在那里放着新的和 _old
Y2038: Ein Beispiel für einen ABI-Bruch unter Berücksichtigung der derzeit laufenden, langsam auftretenden
„Y2038“ ABI-Bruchbeispiele zum besseren Verständnis des Linux-ABI. Im Januar 2038 wird der 32-Bit-Zeitzähler auf Null zurückgesetzt, genau wie der Kilometerzähler älterer Fahrzeuge. Der Januar 2038 mag noch weit weg klingen, aber man kann mit Sicherheit davon ausgehen, dass viele heute verkaufte IoT-Geräte noch betriebsbereit sein werden. So wie die Smart Meter und Intelligentes Parksystem Solche gewöhnlichen Produkte verwenden möglicherweise eine 32-Bit-Prozessorarchitektur und unterstützen möglicherweise keine Software-Updates. Der Linux-Kernel hat intern auf die Verwendung von 64-Bit umgestellt -indent: 0px; display: inline-block;">time_t Undurchsichtiger Datentyp, um einen späteren Zeitpunkt darzustellen. Das bedeutet so etwas wie time()
wurden die Funktionssignaturen auf 64-Bit-Systemen geändert. Das Ausmaß dieser Bemühungen lässt sich deutlich an Kernel-Header-Dateien wie time_types.h erkennen, wo Place new und _alte Version der Datenstruktur.
Stabiles ABI zu verstehen ist etwas schwierig. Zu bedenken ist, dass die meisten sysfs zwar ein stabiles ABI sind, die Debug-Schnittstellen jedoch definitiv instabil sind, weil sie Kernel-Interna dem Benutzerraum zugänglich machen. Linus Torvalds sagte einmal: „Brechen Sie den Userspace nicht kaputt“, und damit meinte er normalerweise den Schutz gewöhnlicher Benutzer, die „nur wollen, dass es funktioniert“, und nicht Systemprogrammierer und Kernel-Ingenieure, die in der Lage sein sollten, die Kernel-Dokumentation und den Quellcode zu lesen, um sie zu verstehen Was hat sich zwischen den Versionen geändert? Das Bild unten verdeutlicht diesen Unterschied.
Stabilitätsgarantien
Es ist unwahrscheinlich, dass der durchschnittliche Benutzer mit instabilen Teilen der Linux-ABI interagiert, Systemprogrammierer können dies jedoch unbeabsichtigt tun. Außer /sys/kernel/debug
Außer sysfs (/sys
) und procfs (/proc
/sys/kernel/debug
以外,sysfs(/sys
)和 procfs(/proc
)的所有部分都是稳定的。
那么其他对用户空间可见的二进制接口如何呢,包括 /dev
中的设备文件、内核日志文件(可通过 dmesg
Gerätedateien und Kernel-Protokolldateien in /dev
(Zugriff über dmesg
command to read), file system metadata or in What about die „Boot-Parameter“, die in der „Befehlszeile“ des Kernels bereitgestellt werden (sichtbar in Bootloadern wie GRUB oder u-boot)? Natürlich „es kommt darauf an.“ Alte Dateisysteme mountenNeben der Tatsache, dass ein Linux-System beim Booten hängt, ist die Unfähigkeit, ein Dateisystem zu mounten, das Enttäuschendste. Befindet sich das Dateisystem auf der SSD eines zahlenden Kunden, ist das Problem wirklich gravierend. Ein Linux-Dateisystem, das unter einer älteren Kernel-Version gemountet werden konnte, sollte auch dann noch gemountet werden können, wenn der Kernel aktualisiert wird, oder? Tatsächlich „es kommt darauf an.“ Im Jahr 2020 beschwerte sich
ein verletzter Linux-Entwickler auf der Mailingliste des Kernels:Der Kernel hat dies als gültiges mountbares Dateisystemformat ohne Fehler oder Probleme jeglicher Art akzeptiert. Warnung, und arbeitet seitdem zuverlässig auf diese Weise Jahre... Ich bin im Allgemeinen davon ausgegangen, dass das Mounten eines vorhandenen Root-Dateisystems in den Bereich des Kernel<->Userspace oder der Kernel<-> bestehenden Systemgrenzen fällt, wie durch das Aktualisieren des Kernels mit vorhandenen Benutzerbereichen und kompatibel sein Systeme, definiert durch das, was vom Kernel akzeptiert und von vorhandenen Benutzerbereichen erfolgreich verwendet wird.
Aber es gibt ein Problem: Diese nicht mountbaren Dateisysteme werden mit einem proprietären Tool erstellt, das auf Flags basiert, die vom Kernel definiert, aber nicht vom Kernel verwendet werden. Dieses Flag erscheint nicht in den API-Headern oder procfs/sysfs von Linux, sondern ist ein Implementierungsdetail. Daher bedeutet die Interpretation dieses Flags im User-Space-Code, sich auf „Undefiniertes Verhalten“ zu verlassen, eine Phrase, die fast jeden Softwareentwickler zum Schaudern bringt. Als die Kernel-Community ihre internen Tests verbesserte und begann, an neuen Konsistenzprüfungen zu arbeiten, begann der Systemaufruf „man 2 mount
“ plötzlich, Dateisysteme mit proprietären Formaten abzulehnen. Da der Ersteller des Formats eindeutig ein Softwareentwickler war, gelang es ihm nicht, die Sympathie der Betreuer des Kernel-Dateisystems zu gewinnen.Auf dem Bauschild steht, dass Teams an den Bäumen arbeiten
🎜Ist das Dateiformat im Verzeichnis /dev
garantiert stabil oder instabil? dmesg-Befehl /dev
目录中的文件格式是否保证稳定或不稳定?dmesg 命令 会从文件 /dev/kmsg
中读取内容。2018 年,一位开发人员 为 dmesg 输出实现了线程化,使内核能够“在打印一系列 printk()
消息到控制台时,不会被中断和/或被其他线程的并发 printk()
干扰”。听起来很棒!通过在 /dev/kmsg
输出的每一行添加线程 ID,实现了线程化。密切关注的读者将意识到这个改动改变了 /dev/kmsg
的 ABI,这意味着解析该文件的应用程序也需要进行相应的修改。由于许多发行版没有编译启用新功能的内核,大多数使用 /bin/dmesg
的用户可能没有注意到这件事,但这个改动破坏了 GDB 调试器 读取内核日志的能力。
确实,敏锐的读者会认为 GDB 的用户运气不佳,因为调试器是开发人员工具。实际上并非如此,因为需要更新以支持新的 /dev/kmsg
liest aus der Datei /dev/kmsg>. Im Jahr 2018 implementierte ein Entwickler Threading <a target="_blank" href="//m.sbmmt.com/link/50d2e70cdf7dd05be85e1b8df3f8ced4"> für die dmesg-Ausgabe, wodurch der Kernel „eine Reihe von printk()</a>
Wenn die Nachricht an die Konsole gesendet wird, wird sie nicht von anderen Threads unterbrochen und/oder bestätigt printk()
Interferenz". Klingt großartig! Von /dev/kmsg
Fügt jeder Ausgabezeile eine Thread-ID hinzu, um Threading zu erreichen. Wer genau hinschaut, wird feststellen, dass sich durch diese Änderung /dev/kmsg
s ABI, was bedeutet, dass die Anwendung, die die Datei analysiert, ebenfalls entsprechend geändert werden muss. Da viele Distributionen den Kernel nicht mit aktivierten neuen Funktionen kompilieren, verwenden die meisten /bin/dmesg
Benutzer bemerken dies möglicherweise nicht, aber diese Änderung unterbricht GDB-Debugger Die Möglichkeit, Kernel-Protokolle zu lesen.
/dev/kmsg
Der Code im Format befindet sich im „in-tree“-Teil des Git-Quellcode-Repositorys des Kernels. Bei einem normalen Projekt wäre es ein offensichtlicher Fehler, wenn Programme innerhalb einer einzelnen Codebasis nicht zusammenarbeiten würden. Daher wurde ein Was ist mit BPF-Programmen? BPF ist ein leistungsstarkes Tool, das im laufenden Kernel überwacht und sogar in Echtzeit konfiguriert werden kann. BPF wurde ursprünglich entwickelt, um die Netzwerkkonfiguration in Echtzeit zu unterstützen, indem es Systemadministratoren ermöglicht, Paketfilter im Handumdrehen über die Befehlszeile zu ändern. Alexei Starovoitov und andere haben BPF stark erweitert, um beliebige Kernelfunktionen verfolgen zu können. Die Ablaufverfolgung ist eindeutig die Domäne von Entwicklern und nicht von normalen Benutzern und unterliegt daher offensichtlich keinen ABI-Garantien (obwohl der Systemaufruf bpf()
die gleichen Stabilitätsversprechen hat wie andere Systemaufrufe). Andererseits eröffnet die Erstellung von BPF-Programmen mit neuer Funktionalität die Möglichkeit, „Kernelmodule als De-facto-Standardmittel zur Erweiterung des Kernels zu ersetzen“. Kernel-Module sorgen dafür, dass Geräte, Dateisysteme, Verschlüsselung, Netzwerke usw. ordnungsgemäß funktionieren. Dies sind natürlich auch Einrichtungen, auf die sich der durchschnittliche Benutzer verlässt, der „einfach nur möchte, dass es funktioniert“. Das Problem besteht darin, dass BPF-Programme im Gegensatz zu den meisten Open-Source-Kernelmodulen traditionell nicht im Kernel-Quellcode enthalten sind.Im Frühjahr 2022 geriet ein Vorschlag
in den Fokus, der vorsah, Unterstützung für eine breite Palette von Human-Interface-Geräten (wie Mäusen und Tastaturen) mithilfe von Mini-BPF-Programmen anstelle von Gerätetreiber-Patches bereitzustellen.Es folgte eine lebhafte Diskussion, aber das Problem wurde offenbar in Torvalds‘ Kommentaren
beim Open Source Summit gelöst: 🎜Er weist darauf hin, dass Sie das Problem beheben müssen, wenn Sie „echte Userspace-Tools, die von normalen (Nicht-Kernel-Entwickler-)Benutzern verwendet werden“ beschädigen, unabhängig davon, ob eBPF verwendet wird oder nicht.
Es scheint sich ein Konsens darüber abzuzeichnen, dass Entwickler, die möchten, dass ihre BPF-Programme nach einem Kernel-Update weiterhin funktionieren, sie an einem noch nicht festgelegten Ort im Kernel-Quellcode-Repository festschreiben müssen. Bleiben Sie auf dem Laufenden, um zu sehen, welche Richtlinien die Kernel-Community in Bezug auf BPF- und ABI-Stabilität übernimmt.
FazitDie ABI-Stabilitätsgarantien des Kernels gelten für procfs, sysfs und die Systemaufrufschnittstelle, es gibt jedoch wichtige Ausnahmen. Wenn eine Kernel-Änderung „In-Tree“-Code oder eine Userspace-Anwendung beschädigt, wird der fehlerhafte Patch oft schnell zurückgesetzt. Bei proprietärem Code, der auf Kernel-Implementierungsdetails basiert, sind diese Details zwar vom Benutzerbereich aus zugänglich, aber nicht geschützt und erfährt nur begrenztes Mitgefühl, wenn etwas schief geht. Wenn Probleme wie Y2038 einen ABI-Bruch nicht verhindern können, erfolgt der Übergang auf möglichst bewusste und systematische Weise. Und neue Funktionen wie BPF-Programme werfen unbeantwortete Fragen zu den Grenzen der ABI-Stabilität auf. DANKEVielen Dank anAkkana Peck, Sarah R. Newman und Luke S. Crawford für ihre hilfreichen Kommentare zu früheren Versionen des Materials.
Das obige ist der detaillierte Inhalt vonErfahren Sie in zehn Minuten mehr über Linux ABI. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!