如何裝載/卸載Linux內(nèi)核模塊
找到并裝載內(nèi)核模塊以解決外設(shè)問題。
本文來自 Manning 出版的 Linux in Action 的第 15 章。
Linux 使用內(nèi)核模塊管理硬件外設(shè)。 我們來看看它是如何工作的。
運(yùn)行中的 Linux 內(nèi)核是您不希望被破壞的東西之一。畢竟,內(nèi)核是驅(qū)動(dòng)計(jì)算機(jī)所做的一切工作的軟件??紤]到在一個(gè)運(yùn)行的系統(tǒng)上必須同時(shí)管理諸多細(xì)節(jié),最好能讓內(nèi)核盡可能的減少分心,專心的完成它的工作。但是,如果對(duì)計(jì)算環(huán)境進(jìn)行任何微小的更改都需要重啟整個(gè)系統(tǒng),那么插入一個(gè)新的網(wǎng)絡(luò)攝像頭或打印機(jī)就可能會(huì)嚴(yán)重影響您的工作流程。每次添加設(shè)備時(shí)都必須重新啟動(dòng),以使系統(tǒng)識(shí)別它,這效率很低。
為了在穩(wěn)定性和可用性之間達(dá)成有效的平衡,Linux 將內(nèi)核隔離,但是允許您通過可加載內(nèi)核模塊 (LKM) 實(shí)時(shí)添加特定的功能。如下圖所示,您可以將模塊視為軟件的一部分,它告訴內(nèi)核在哪里找到一個(gè)設(shè)備以及如何使用它。反過來,內(nèi)核使設(shè)備對(duì)用戶和進(jìn)程可用,并監(jiān)視其操作。
內(nèi)核模塊充當(dāng)設(shè)備和 Linux 內(nèi)核之間的轉(zhuǎn)換器。
雖然你可以自己編寫模塊來完全按照你喜歡的方式來支持一個(gè)設(shè)備,但是為什么要這樣做呢?Linux 模塊庫已經(jīng)非常強(qiáng)大,通常不需要自己去實(shí)現(xiàn)一個(gè)模塊。 而絕大多數(shù)時(shí)候,Linux 會(huì)自動(dòng)加載新設(shè)備的模塊,而您甚至不知道它。
不過,有時(shí)候,出于某種原因,它本身并不會(huì)自動(dòng)進(jìn)行。(你肯定不想讓那個(gè)招聘經(jīng)理不耐煩地一直等待你的笑臉加入視頻面試。)為了幫助你解決問題,你需要更多地了解內(nèi)核模塊,特別是,如何找到運(yùn)行你的外設(shè)的實(shí)際模塊,然后如何手動(dòng)激活它。
查找內(nèi)核模塊
按照公認(rèn)的約定,內(nèi)核模塊是位于 /lib/modules/
目錄下的具有 .ko(內(nèi)核對(duì)象)擴(kuò)展名的文件。 然而,在你找到這些文件之前,你還需要選擇一下。因?yàn)樵谝龑?dǎo)時(shí)你需要從版本列表中選擇其一加載,所以支持您選擇的特定軟件(包括內(nèi)核模塊)必須存在某處。 那么,/lib/modules/
就是其中之一。 你會(huì)發(fā)現(xiàn)目錄里充滿了每個(gè)可用的 Linux 內(nèi)核版本的模塊; 例如:
$ ls /lib/modules
4.4.0-101-generic
4.4.0-103-generic
4.4.0-104-generic
在我的電腦上,運(yùn)行的內(nèi)核是版本號(hào)最高的版本(4.4.0-104-generic),但不能保證這對(duì)你來說是一樣的(內(nèi)核經(jīng)常更新)。 如果您將要在一個(gè)運(yùn)行的系統(tǒng)上使用模塊完成一些工作的話,你需要確保您找到正確的目錄樹。
好消息:有一個(gè)可靠的竅門。相對(duì)于通過名稱來識(shí)別目錄,并希望能夠找到正確的目錄,你可以使用始終指向使用的內(nèi)核名稱的系統(tǒng)變量。 您可以使用 uname -r
( -r
從系統(tǒng)信息中指定通常顯示的內(nèi)核版本號(hào))來調(diào)用該變量:
$ uname -r
4.4.0-104-generic
通過這些信息,您可以使用稱為命令替換的過程將 uname
并入您的文件系統(tǒng)引用中。 例如,要導(dǎo)航到正確的目錄,您需要將其添加到 /lib/modules
。 要告訴 Linux “uname” 不是一個(gè)文件系統(tǒng)中的位置,請(qǐng)將 uname
部分用反引號(hào)括起來,如下所示:
$ ls /lib/modules/`uname -r`
build modules.alias modules.dep modules.softdep
initrd modules.alias.bin modules.dep.bin modules.symbols
kernel modules.builtin modules.devname modules.symbols.bin
misc modules.builtin.bin modules.order vdso
你可以在 kernel/
目錄下的子目錄中找到大部分模塊。 花幾分鐘時(shí)間瀏覽這些目錄,了解事物的排列方式和可用內(nèi)容。 這些文件名通常會(huì)讓你知道它們是什么。
$ ls /lib/modules/`uname -r`/kernel
arch crypto drivers fs kernel lib mm
net sound ubuntu virt zfs
這是查找內(nèi)核模塊的一種方法;實(shí)際上,這是一種快速的方式。 但這不是唯一的方法。 如果你想獲得完整的集合,你可以使用 lsmod
列出所有當(dāng)前加載的模塊以及一些基本信息。 這個(gè)截?cái)噍敵龅牡谝涣校ㄔ谶@里列出的太多了)是模塊名稱,后面是文件大小和數(shù)量,然后是每個(gè)模塊的名稱:
$ lsmod
[...]
vboxdrv 454656 3 vboxnetadp,vboxnetflt,vboxpci
rt2x00usb 24576 1 rt2800usb
rt2800lib 94208 1 rt2800usb
[...]
到底有多少?好吧,我們?cè)龠\(yùn)行一次 lsmod
,但是這一次將輸出管道輸送到 wc -l
看一下一共多少行:
$ lsmod | wc -l
113
這是已加載的模塊。 總共有多少個(gè)? 運(yùn)行 modprobe -c
并計(jì)算這些行將給我們這個(gè)數(shù)字:
$ modprobe -c | wc -l
33350
有 33,350 個(gè)可用模塊!? 看起來好像有人多年來一直在努力為我們提供軟件來驅(qū)動(dòng)我們的物理設(shè)備。
注意:在某些系統(tǒng)中,您可能會(huì)遇到自定義的模塊,這些模塊要么在 /etc/modules
文件中使用獨(dú)特的條目進(jìn)行引用,要么在 /etc/modules-load.d/
下的配置文件中。這些模塊很可能是本地開發(fā)項(xiàng)目的產(chǎn)物,可能涉及前沿實(shí)驗(yàn)。不管怎樣,知道你看到的是什么總是好的。
這就是如何找到模塊的方法。 如果出于某種原因,它不會(huì)自行加載,您的下一個(gè)工作就是弄清楚如何手動(dòng)加載未激活的模塊。
手動(dòng)加載內(nèi)核模塊
在加載內(nèi)核模塊之前,邏輯上您必須確認(rèn)它存在。在這之前,你需要知道它叫什么。要做到這一點(diǎn),有時(shí)需要兼有魔法和運(yùn)氣以及在線文檔作者的辛勤工作的幫助。
我將通過描述一段時(shí)間前遇到的問題來說明這個(gè)過程。在一個(gè)晴朗的日子里,出于某種原因,筆記本電腦上的 WiFi 接口停止工作了。就這樣。也許是軟件升級(jí)把它搞砸了。誰知道呢?我運(yùn)行了 lshw -c network
,得到了這個(gè)非常奇怪的信息:
network UNCLAIMED
AR9485 Wireless Network Adapter
Linux 識(shí)別到了接口(Atheros AR9485),但將其列為未聲明。 那么,正如他們所說的那樣,“當(dāng)情況變得嚴(yán)峻時(shí),就會(huì)在互聯(lián)網(wǎng)上進(jìn)行艱難的搜索。” 我搜索了一下 atheros ar9 linux 模塊,在瀏覽了一頁又一頁五年前甚至是十年前的頁面后,它們建議我自己寫個(gè)模塊或者放棄吧,然后我終于發(fā)現(xiàn)(最起碼 Ubuntu 16.04)有一個(gè)可以工作的模塊。 它的名字是 ath9k 。
是的! 這場(chǎng)戰(zhàn)斗勝券在握!向內(nèi)核添加模塊比聽起來容易得多。 要仔細(xì)檢查它是否可用,可以針對(duì)模塊的目錄樹運(yùn)行 find
,指定 -type f
來告訴 Linux 您正在查找文件,然后將字符串 ath9k
和星號(hào)一起添加以包含所有以你的字符串打頭的文件:
$ find /lib/modules/$(uname -r) -type f -name ath9k*
/lib/modules/4.4.0-97-generic/kernel/drivers/net/wireless/ath/ath9k/ath9k_common.ko
/lib/modules/4.4.0-97-generic/kernel/drivers/net/wireless/ath/ath9k/ath9k.ko
/lib/modules/4.4.0-97-generic/kernel/drivers/net/wireless/ath/ath9k/ath9k_htc.ko
/lib/modules/4.4.0-97-generic/kernel/drivers/net/wireless/ath/ath9k/ath9k_hw.ko
再一步,加載模塊:
# modprobe ath9k
就是這樣。無啟動(dòng),沒煩惱。
這里還有一個(gè)示例,向您展示如何使用已經(jīng)崩潰的運(yùn)行模塊。曾經(jīng)有一段時(shí)間,我使用羅技網(wǎng)絡(luò)攝像頭和一個(gè)特定的軟件會(huì)使攝像頭在下次系統(tǒng)啟動(dòng)前無法被任何其他程序訪問。有時(shí)我需要在不同的應(yīng)用程序中打開相機(jī),但沒有時(shí)間關(guān)機(jī)重新啟動(dòng)。(我運(yùn)行了很多應(yīng)用程序,在引導(dǎo)之后將它們?nèi)繙?zhǔn)備好需要一些時(shí)間。)
由于這個(gè)模塊可能是運(yùn)行的,所以使用 lsmod
來搜索 video 這個(gè)詞應(yīng)該給我一個(gè)關(guān)于相關(guān)模塊名稱的提示。 實(shí)際上,它比提示更好:用 video 這個(gè)詞描述的唯一模塊是 uvcvideo(如下所示):
$ lsmod | grep video
uvcvideo 90112 0
videobuf2_vmalloc 16384 1 uvcvideo
videobuf2_v4l2 28672 1 uvcvideo
videobuf2_core 36864 2 uvcvideo,videobuf2_v4l2
videodev 176128 4 uvcvideo,v4l2_common,videobuf2_core,videobuf2_v4l2
media 24576 2 uvcvideo,videodev
有可能是我自己的操作導(dǎo)致了崩潰,我想我可以挖掘更深一點(diǎn),看看我能否以正確的方式解決問題。但結(jié)果你知道的;有時(shí)你不關(guān)心理論,只想讓設(shè)備工作。 所以我用 rmmod
殺死了 uvcvideo
模塊,然后用 modprobe
重新啟動(dòng)它,一切都好:
# rmmod uvcvideo
# modprobe uvcvideo
再一次:不重新啟動(dòng)。沒有其他的后續(xù)影響。