LWN:5.13 內(nèi)核中導(dǎo)出符號(hào)的變化!
關(guān)注了就能看到更多這么棒的文章哦~
Exported-symbol changes in 5.13
By Jonathan Corbet
May 17, 2021
DeepL assisted translation
https://lwn.net/Articles/856312/
多年來(lái),內(nèi)核社區(qū)對(duì)于是否將 kernel 內(nèi)部?jī)?nèi)核符號(hào)(kernel symbol)導(dǎo)出供 loadable module 使用,一直存在著很多爭(zhēng)議。導(dǎo)出(export)符號(hào)表,一般來(lái)說(shuō)就會(huì)將具體實(shí)現(xiàn)細(xì)節(jié)暴露給了外部代碼,也就是可能會(huì)被按照意料之外的一些方式來(lái)使用(或?yàn)E用),并且未來(lái)要想再對(duì)這些函數(shù)進(jìn)行修改的話就會(huì)面臨極大的困難。目前并沒(méi)有任何機(jī)構(gòu)來(lái)監(jiān)管 symbol export,也沒(méi)有什么官方流程來(lái)對(duì)這些 export 進(jìn)行批準(zhǔn)。每次都是有人發(fā)現(xiàn)了他們希望看到的改動(dòng)時(shí),才會(huì)有相關(guān)討論出現(xiàn)。但是,我們可以很容易地對(duì)比出新的 kernel 版本比起之前來(lái)說(shuō)有哪些 export symbol 發(fā)生了變化,這樣一來(lái)我們就可以了解到底層究竟發(fā)生了哪些變化。
內(nèi)核有數(shù)千個(gè)的函數(shù)以及數(shù)據(jù)結(jié)構(gòu),其中大多數(shù)都是某些源文件自己的私有內(nèi)容,其他的則是整個(gè)內(nèi)核都可以使用的。但 loadable module 的地位很特殊,它們只能訪問(wèn)那些用 EXPORT_SYMBOL()(或它的其他變體) 明確 export 出來(lái)的符號(hào)。內(nèi)核 Image 代碼可以使用的符號(hào)中,有很多都是 loadable module 無(wú)法使用的。這樣做的目的是為了使 module 的接口數(shù)量盡量少一些,方便管理。
不過(guò),這個(gè)目標(biāo)目前看來(lái)并未實(shí)現(xiàn)。5.12 版的 kernel 向 module 總共 export 了 31695 個(gè)符號(hào),這并不是一個(gè)數(shù)量很少的接口列表。這個(gè)數(shù)字在 5.13-rc1 中增長(zhǎng)到了 31822 個(gè)。這意味著增加了 127 個(gè)符號(hào),但實(shí)際情況比這更復(fù)雜,在這段時(shí)間里有 244 個(gè)之前 export 的符號(hào)被刪除,而新增了 371 個(gè)。細(xì)節(jié)可以在這個(gè)頁(yè)面(https://lwn.net/Articles/856313/)上看到。
有些改動(dòng)其實(shí)不算是新增或刪除,實(shí)際上是改了個(gè)名字。例如,pmbus_do_probe()在 5.13 中就不再按照這個(gè)名字 export 了,它現(xiàn)在(按照編者隨便定義的標(biāo)記來(lái)說(shuō)的話)是 PMBUS::pmbus_do_probe()。換句話說(shuō),這個(gè)符號(hào)已經(jīng)從全局命名空間(global namespace)移到了子系統(tǒng)自己特定的 namespace。2018 年開始支持對(duì) kernel symbol export 時(shí)使用 namespace,但目前看來(lái)進(jìn)展不是很快。5.13 內(nèi)核增加了一個(gè)新的 namespace(PMBUS),這個(gè)子系統(tǒng)內(nèi)的 export symbol 都正在遷移過(guò)來(lái)。現(xiàn)在內(nèi)核中有 18 個(gè)關(guān)于 symbol 的 namespace:
CRYPTO_INTERNAL, FIRMWARE_LOADER_PRIVATE, LTC2497, MCB, NVME_TARGET_PASSTHRU, PMBUS, SND_INTEL_SOUNDWIRE_ACPI, SND_SOC_SOF_INTEL_HDA_COMMON, SND_SOC_SOF_MERRIFIELD, SND_SOC_SOF_HDA_AUDIO_CODEC, SND_SOC_SOF_HDA_AUDIO_CODEC_I915, SND_SOC_SOF_INTEL_HIFI_EP_IPC, SND_SOC_SOF_INTEL_HIFI_EP_IPC, SND_SOC_SOF_ACPI_DEV, SND_SOC_SOF_PCI_DEV, SND_SOC_SOF_XTENSA, SOUNDWIRE_INTEL_INIT, and TEST_FIRMWARE.
顯然,目前位置 sound 子系統(tǒng)是最熱心的 symbol namespace 用戶。
export 出來(lái)的 symbol 中,許多其他改動(dòng)都是來(lái)自于內(nèi)核內(nèi)部的代碼重構(gòu)。在 bit-finding library 中再進(jìn)行一些優(yōu)化,導(dǎo)致 find_first_bit() 這類函數(shù)都變成了頭文件中的 inline 函數(shù),這些函數(shù)不再需要 export。但它們底層調(diào)用的 find_first_bit() 之類的函數(shù),現(xiàn)在就需要 export 了。vmem_map 這個(gè)通用符號(hào)是專門針對(duì) ia64 架構(gòu)的,既然 ia64 放棄了對(duì) VMEMMAP memory model 的支持,那么這個(gè) symbol 也就被移除了。wimax 相關(guān)的 symbol 已經(jīng)跟著那些不再流行的 WiMAX 驅(qū)動(dòng)程序一起消失了。像 rt_mutex_destroy() 這樣的函數(shù)被刪除了則是因?yàn)樗鼈儧](méi)有什么地方會(huì)用到。
新增的許多 symbol 都是跟新功能相對(duì)應(yīng)的。例如,alloc_pages() 就是跟著 batch page allocation 這個(gè)功能一起加進(jìn)來(lái)的。還有一些 symbol 就不那么清晰易懂了,比如說(shuō),dotdot_name 是什么意思?相關(guān)的 commit 中指出這是一個(gè) "會(huì)有用的常量:用于表示'…'的 struct qstr",很多人估計(jì)會(huì)覺(jué)得這個(gè)說(shuō)法很難理解。它實(shí)際上是為文件系統(tǒng)代碼提供了一個(gè)快捷方式,使其能夠引用名為 "… " 的目錄,不用再將其封裝在 "quick string" structure(用于在虛擬文件系統(tǒng)層中傳遞字符串)之中了。有些文件系統(tǒng)在 5.13 中開始使用它。
一般來(lái)說(shuō),如果 mainline kernel 中沒(méi)有地方會(huì)用到某個(gè) kernel symbol 的話,它就不應(yīng)該被 export。這條規(guī)則通常是被遵守的,但也有一些例外。舉個(gè)例子,zynqmp_pm_pinctrl_get_function()在 5.13-rc1 中被 export 出來(lái),但 kernel 里面并沒(méi)有地方在用。其他許多也被 export 出來(lái)的 zynqmp_ 開頭的符號(hào)(都與 Xilinx Zynq SoC 有關(guān))也沒(méi)有被廣泛使用,看起來(lái)都應(yīng)該隱藏在它們自己的 namespace 中。另一個(gè)導(dǎo)出但未被使用的符號(hào)是 __cfi_slowpath_diag(),這是 Clang control-flow-integrity 實(shí)現(xiàn)代碼的一部分,也在本次合并窗口之內(nèi)被合并了。導(dǎo)出這個(gè)符號(hào)的原因尚不完全清楚。__cpu_dying_mask()也是在 5.13 中引入并 export 的,內(nèi)核中也沒(méi)有地方使用到。還有許多其他類似情況。"先導(dǎo)出,以備不時(shí)之需" 似乎是內(nèi)核開發(fā)者的一個(gè)常見(jiàn)習(xí)慣。
在 5.13 內(nèi)核中,增加了 11 個(gè) devm_ 開頭的 export 符號(hào),還有兩個(gè)內(nèi)部使用的__devm_開頭的符號(hào)。并非所有這些都已經(jīng)被用起來(lái)了,但它們確實(shí)是典型的、人們希望 export 出去的符號(hào)。這些函數(shù)是用來(lái)做 "managed device",也就是使編寫設(shè)備驅(qū)動(dòng)程序更容易,并在 device 關(guān)閉時(shí)方便釋放所分配的資源,從而更加安全?,F(xiàn)在已經(jīng)有超過(guò) 300 個(gè)這樣的函數(shù)被 export 到 module 之中,而且這個(gè)列表看起來(lái)還會(huì)繼續(xù)增加。
direct rendering manager(DRM)圖形子系統(tǒng)這次增加了 17 個(gè) drm_ 開頭的 export symbol。DRM 顯然是內(nèi)核中最復(fù)雜的驅(qū)動(dòng) API 之一,在 5.13 中導(dǎo)出的符號(hào)不少于 850 個(gè)。人們開始理解為什么這個(gè)子系統(tǒng)的開發(fā)者會(huì)把文檔放在第一優(yōu)先級(jí)。如果沒(méi)有文檔,這些 API 就很難使用了。當(dāng)然,這也是因?yàn)?graphics processor 都是很復(fù)雜的設(shè)備,所以 API 會(huì)很多。
既然 kernel 提供了接近 32000 個(gè) export symbol,還號(hào)稱是一個(gè) "盡量縮小規(guī)模" 的 module 接口,可以說(shuō)明內(nèi)核整體來(lái)說(shuō)也是一個(gè)非常復(fù)雜的環(huán)境。這種復(fù)雜性反映在很多地方,比如它提供給用戶空間的接口越來(lái)越多,提供給 loadable module 接口越來(lái)越多。多年來(lái),這些接口的規(guī)模已經(jīng)增加了許多,并且往往沒(méi)有經(jīng)過(guò)深入的 review。好消息是,export symbol 還是算作是 kernel 的內(nèi)部接口,也就是隨時(shí)可以更改。因此,也許將來(lái)有一天這個(gè) list 會(huì)變小也說(shuō)不定,但 5.13 周期里是不會(huì)發(fā)生這個(gè)情況了。
全文完
LWN 文章遵循 CC BY-SA 4.0 許可協(xié)議。
長(zhǎng)按下面二維碼關(guān)注,關(guān)注 LWN 深度文章以及開源社區(qū)的各種新近言論~
