自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

十分鐘讓你了解 Linux ABI

系統(tǒng) Linux
熟悉 ABI 的概念、ABI 穩(wěn)定性的重要性以及 Linux 穩(wěn)定 ABI 中包含的內(nèi)容。

LCTT 譯注:昨天,AlmaLinux 稱將 放棄 對 RHEL 的 1:1 兼容性,但將保持對 RHEL 的 ABI 兼容,以便在 RHEL 上運行的軟件可以無縫地運行在 AlmaLinux 上??赡苡械耐瑢W對 ABI 的概念還不是很清楚,因此翻譯此文供大家了解。

許多 Linux 愛好者都熟悉 Linus Torvalds 的 著名告誡:“我們不破壞用戶空間”,但可能并非每個聽到這句話的人都清楚其含義。

這個“第一規(guī)則”提醒開發(fā)人員關(guān)于應用程序的二進制接口(ABI)的穩(wěn)定性,該接口用于應用程序與內(nèi)核之間的通信和配置。接下來的內(nèi)容旨在使讀者熟悉 ABI 的概念,闡述為什么 ABI 的穩(wěn)定性很重要,并討論 Linux 穩(wěn)定 ABI 中包含了哪些內(nèi)容。Linux 的持續(xù)增長和演進需要對 ABI 進行變更,其中一些變更引起了爭議。

什么是 ABI?

ABI 表示 應用程序二進制接口Applications Binary Interface。理解 ABI 概念的一種方式是考慮它與其他概念的區(qū)別。對于許多開發(fā)人員來說,應用程序編程接口Applications Programming Interface(API)更為熟悉。通常,庫的頭文件和文檔被認為是其 API,以及還有像 HTML5 這樣的標準文檔。調(diào)用庫或交換字符串格式數(shù)據(jù)的程序必須遵守 API 中所描述的約定,否則可能得到意外的結(jié)果。

ABI 類似于 API,因為它們規(guī)定了命令的解釋和二進制數(shù)據(jù)的交換方式。對于 C 程序,ABI 通常包括函數(shù)的返回類型和參數(shù)列表、結(jié)構(gòu)體的布局,以及枚舉類型的含義、順序和范圍。截至 2022 年,Linux 內(nèi)核仍然幾乎完全是 C 程序,因此必須遵守這些規(guī)范。

內(nèi)核系統(tǒng)調(diào)用接口” 的描述可以在《Linux 手冊第 2 節(jié)》中找到,并包括了可從中間件應用程序調(diào)用的類似 mount 和 sync 的 C 版本函數(shù)。這些函數(shù)的二進制布局是 Linux ABI 的第一個重要組成部分。對于問題 “Linux 的穩(wěn)定 ABI 包括哪些內(nèi)容?”,許多用戶和開發(fā)人員的回答是 “sysfs(/sys)和 procfs(/proc)的內(nèi)容”。而實際上,官方 Linux ABI 文檔 確實主要集中在這些 虛擬文件系統(tǒng) 上。

前面著重介紹了 Linux ABI 在程序中的應用方式,但未涵蓋同等重要的人為因素。正如下圖所示,ABI 的功能需要內(nèi)核社區(qū)、C 編譯器(如 GCC 或 clang)、創(chuàng)建用戶空間 C 庫(通常是 glibc)的開發(fā)人員,以及按照 可執(zhí)行與鏈接格式(ELF) 布局的二進制應用程序之間的合作努力。

開發(fā)社區(qū)內(nèi)的合作開發(fā)社區(qū)內(nèi)的合作

為什么我們關(guān)注 ABI?

來自 Torvalds 本人的 Linux ABI 的穩(wěn)定性保證,使得 Linux 發(fā)行版和個人用戶能夠獨立更新內(nèi)核,而不受操作系統(tǒng)的影響。

如果 Linux 沒有穩(wěn)定的 ABI,那么每次內(nèi)核需要修補以解決安全問題時,操作系統(tǒng)的大部分甚至全部內(nèi)容都需要重新安裝。顯然,二進制接口的穩(wěn)定性是 Linux 的可用性和廣泛采用的重要因素之一。

Terminal outputTerminal output

如上圖所示,內(nèi)核(在 linux-libc-dev 中)和 Glibc(在 libc6-dev 中)都提供了定義文件權(quán)限的位掩碼。顯然,這兩個定義集必須一致!apt 軟件包管理器會識別軟件包提供每個文件。Glibc ABI 的潛在不穩(wěn)定部分位于 bits/ 目錄中。

在大部分情況下,Linux ABI 的穩(wěn)定性保證運作良好。按照 

Y2038:一個 ABI 破壞的例子

通過考慮當前正在進行的、緩慢發(fā)生 的 “Y2038” ABI 破壞的例子,可以更好地理解 Linux ABI。在 2038 年 1 月,32 位時間計數(shù)器將回滾到全零,就像較舊車輛的里程表一樣。2038 年 1 月聽起來還很遙遠,但可以肯定的是,如今銷售的許多物聯(lián)網(wǎng)設(shè)備仍將處于運行狀態(tài)。像今年安裝的 智能電表 和 智能停車系統(tǒng) 這樣的普通產(chǎn)品可能采用的是 32 位處理器架構(gòu),而且也可能不支持軟件更新。

Linux 內(nèi)核已經(jīng)在內(nèi)部轉(zhuǎn)向使用 64 位的 time_t 不透明數(shù)據(jù)類型來表示更晚的時間點。這意味著像 time() 這樣的系統(tǒng)調(diào)用在 64 位系統(tǒng)上已經(jīng)變更了它們的函數(shù)簽名。這些努力的艱難程度可以在內(nèi)核頭文件中(例如 time_types.h)清楚地看到,在那里放著新的和 _old 版本的數(shù)據(jù)結(jié)構(gòu)。

里程表翻轉(zhuǎn)里程表翻轉(zhuǎn)

Glibc 項目也 支持 64 位時間,那么就大功告成了,對嗎?不幸的是,根據(jù) Debian 郵件列表中的討論 來看,情況并非如此。發(fā)行版面臨難以選擇的問題,要么為 32 位系統(tǒng)提供所有二進制軟件包的兩個版本,要么為安裝介質(zhì)提供兩個版本。在后一種情況下,32 位時間的用戶將不得不重新編譯其應用程序并重新安裝。正如往常一樣,專有應用程序才是一個真正的頭疼問題。

Linux 穩(wěn)定 ABI 里到底包括什么內(nèi)容?

理解穩(wěn)定 ABI 有些微妙。需要考慮的是,盡管大部分 sysfs 是穩(wěn)定 ABI,但調(diào)試接口肯定是不穩(wěn)定的,因為它們將內(nèi)核內(nèi)部暴露給用戶空間。Linus Torvalds 曾表示,“不要破壞用戶空間”,通常情況下,他是指保護那些 “只想它能工作” 的普通用戶,而不是系統(tǒng)程序員和內(nèi)核工程師,后者應該能夠閱讀內(nèi)核文檔和源代碼,以了解不同版本之間發(fā)生了什么變化。下圖展示了這個區(qū)別。

穩(wěn)定性保證穩(wěn)定性保證

普通用戶不太可能與 Linux ABI 的不穩(wěn)定部分進行交互,但系統(tǒng)程序員可能無意中這樣做。除了 /sys/kernel/debug 以外,sysfs(/sys)和 procfs(/proc)的所有部分都是穩(wěn)定的。

那么其他對用戶空間可見的二進制接口如何呢,包括 /dev 中的設(shè)備文件、內(nèi)核日志文件(可通過 dmesg 命令讀取)、文件系統(tǒng)元數(shù)據(jù)或在內(nèi)核的 “命令行” 中提供的 “引導參數(shù)”(在引導加載程序如 GRUB 或 u-boot 中可見)呢?當然,“這要視情況而定”。

掛載舊文件系統(tǒng)

除了 Linux 系統(tǒng)在引導過程中出現(xiàn)掛起之外,文件系統(tǒng)無法掛載是最令人失望的事情。如果文件系統(tǒng)位于付費客戶的固態(tài)硬盤上,那么問題確實十分嚴重。當內(nèi)核升級時,一個能夠在舊內(nèi)核版本下掛載的 Linux 文件系統(tǒng)應該仍然能夠掛載,對嗎?實際上,“這要視情況而定”。

在 2020 年,一位受到傷害的 Linux 開發(fā)人員在內(nèi)核的郵件列表上 抱怨道

內(nèi)核已經(jīng)接受這個作為一個有效的可掛載文件系統(tǒng)格式,沒有任何錯誤或任何類型的警告,而且已經(jīng)這樣穩(wěn)定地工作了多年……我一直普遍地以為,掛載現(xiàn)有的根文件系統(tǒng)屬于內(nèi)核<->用戶空間或內(nèi)核<->現(xiàn)有系統(tǒng)邊界的范圍,由內(nèi)核接受并被現(xiàn)有用戶空間成功使用的內(nèi)容所定義,升級內(nèi)核應該與現(xiàn)有用戶空間和系統(tǒng)兼容。

但是有一個問題:這些無法掛載的文件系統(tǒng)是使用一種依賴于內(nèi)核定義,但并未被內(nèi)核使用的標志的專有工具創(chuàng)建的。該標志未出現(xiàn)在 Linux 的 API 頭文件或 procfs/sysfs 中,而是一種 實現(xiàn)細節(jié)。因此,在用戶空間代碼中解釋該標志意味著依賴于“未定義行為”,這是個幾乎會讓每個軟件開發(fā)人員都感到戰(zhàn)栗的短語。當內(nèi)核社區(qū)改進其內(nèi)部測試并開始進行新的一致性檢查時,“man 2 mount” 系統(tǒng)調(diào)用突然開始拒絕具有專有格式的文件系統(tǒng)。由于該格式的創(chuàng)建者明確是一位軟件開發(fā)人員,因此他未能得到內(nèi)核文件系統(tǒng)維護者的同情。

施工標志上寫著工作人員在樹上進行工作施工標志上寫著工作人員在樹上進行工作

線程化內(nèi)核的 dmesg 日志

/dev 目錄中的文件格式是否保證穩(wěn)定或不穩(wěn)定?dmesg 命令 會從文件 /dev/kmsg 中讀取內(nèi)容。2018 年,一位開發(fā)人員 為 dmesg 輸出實現(xiàn)了線程化,使內(nèi)核能夠“在打印一系列 printk() 消息到控制臺時,不會被中斷和/或被其他線程的并發(fā) printk() 干擾”。聽起來很棒!通過在 /dev/kmsg 輸出的每一行添加線程 ID,實現(xiàn)了線程化。密切關(guān)注的讀者將意識到這個改動改變了 /dev/kmsg 的 ABI,這意味著解析該文件的應用程序也需要進行相應的修改。由于許多發(fā)行版沒有編譯啟用新功能的內(nèi)核,大多數(shù)使用 /bin/dmesg 的用戶可能沒有注意到這件事,但這個改動破壞了 GDB 調(diào)試器 讀取內(nèi)核日志的能力。

確實,敏銳的讀者會認為 GDB 的用戶運氣不佳,因為調(diào)試器是開發(fā)人員工具。實際上并非如此,因為需要更新以支持新的 /dev/kmsg 格式的代碼位于內(nèi)核自己的 Git 源代碼庫的 “樹內(nèi)” 部分。對于一個正常的項目來說,單個代碼庫內(nèi)的程序無法協(xié)同工作就是一個明顯的錯誤,因此已經(jīng)合并了一份 使 GDB 能夠與線程化的 /dev/kmsg 一起工作的補丁。

那么 BPF 程序呢?

BPF 是一種強大的工具,可以在運行的內(nèi)核中監(jiān)控甚至實時進行配置。BPF 最初的目的是通過允許系統(tǒng)管理員即時從命令行修改數(shù)據(jù)包過濾器,從而支持實時網(wǎng)絡配置。Alexei Starovoitov 和其他人極大地擴展了 BPF,使其能夠跟蹤任意內(nèi)核函數(shù)。跟蹤明顯是開發(fā)人員的領(lǐng)域,而不是普通用戶,因此它顯然不受任何 ABI 保證的約束(盡管 bpf() 系統(tǒng)調(diào)用 具有與其他系統(tǒng)調(diào)用相同的穩(wěn)定性承諾)。另一方面,創(chuàng)建新功能的 BPF 程序為“取代內(nèi)核模塊成為擴展內(nèi)核的事實標準手段”提供了可能性。內(nèi)核模塊使設(shè)備、文件系統(tǒng)、加密、網(wǎng)絡等工作正常,因此明顯是“只希望它工作”的普通用戶所依賴的設(shè)施。問題是,與大多數(shù)開源內(nèi)核模塊不同,BPF 程序傳統(tǒng)上不在內(nèi)核源代碼中。

2022 年春季,一個提案 成為了焦點,該提案提議使用微型 BPF 程序而不是設(shè)備驅(qū)動程序補丁,對廣泛的人機接口設(shè)備(如鼠標和鍵盤)提供支持。

隨后進行了一場激烈的討論,但這個問題顯然在 Torvalds 在開源峰會上的評論 中得到解決:

他指出,如果你破壞了“普通(非內(nèi)核開發(fā)人員)用戶使用的真實用戶空間工具”,那么你需要修復它,無論是否使用了 eBPF。

一致意見似乎正在形成,即希望其 BPF 程序在內(nèi)核更新后仍能正常工作的開發(fā)人員 將需要將其提交到內(nèi)核源代碼庫中一個尚未指定的位置。敬請關(guān)注后繼發(fā)展,以了解內(nèi)核社區(qū)對于 BPF 和 ABI 穩(wěn)定性將采取什么樣的政策。

結(jié)論

內(nèi)核的 ABI 穩(wěn)定性保證適用于 procfs、sysfs 和系統(tǒng)調(diào)用接口,但也存在重要的例外情況。當內(nèi)核變更破壞了“樹內(nèi)”代碼或用戶空間應用程序時,通常會迅速回滾有問題的補丁。對于依賴內(nèi)核實現(xiàn)細節(jié)的專有代碼,盡管這些細節(jié)可以從用戶空間訪問,但它并沒有受到保護,并且在出現(xiàn)問題時得到的同情有限。當像 Y2038 這樣的問題無法避免 ABI 破壞時,會以盡可能慎重和系統(tǒng)化的方式進行過渡。而像 BPF 程序這樣的新功能提出了關(guān)于 ABI 穩(wěn)定性邊界的尚未解答的問題。

致謝

感謝 Akkana Peck、Sarah R. Newman 和 Luke S. Crawford 對早期版本材料的有益評論。

責任編輯:龐桂玉 來源: Linux中國
相關(guān)推薦

2024-06-19 09:58:29

2024-05-13 09:28:43

Flink SQL大數(shù)據(jù)

2024-11-07 16:09:53

2015-11-06 11:03:36

2021-07-29 08:57:23

ViteReact模塊

2020-12-09 16:41:22

LinuxIT開發(fā)

2023-10-11 08:18:55

DjangoPython

2009-11-03 11:01:45

VB.NET遠程事件

2025-03-18 12:20:00

編程

2024-12-13 15:29:57

SpringSpringBeanJava

2024-10-08 11:12:12

2020-12-17 06:48:21

SQLkafkaMySQL

2019-04-01 14:59:56

負載均衡服務器網(wǎng)絡

2022-03-21 08:05:38

HTTP/1.1QUIC協(xié)議

2024-10-06 12:50:25

2021-09-07 09:40:20

Spark大數(shù)據(jù)引擎

2022-06-16 07:31:41

Web組件封裝HTML 標簽

2023-04-12 11:18:51

甘特圖前端

2009-04-29 17:35:47

LinuxWebMail系統(tǒng)

2015-09-06 09:22:24

框架搭建快速高效app
點贊
收藏

51CTO技術(shù)棧公眾號