一. 內(nèi)核模塊加載情況查詢
Linux提供了三種方法查詢加載到內(nèi)核的模塊,一種方法是直接訪問proc虛擬文件系統(tǒng)獲取,一種方法則是比較常用的lsmod方法獲取,而lsmod的輸出其實(shí)是基于/proc/modules。另外還有一種就是查看/sys/module/目錄下是否生成已加載模塊的目錄。
1、/proc/modules文件
Linux 內(nèi)核提供了一種通過 /proc 文件系統(tǒng),在運(yùn)行時訪問內(nèi)核內(nèi)部數(shù)據(jù)結(jié)構(gòu)、改變內(nèi)核設(shè)置的機(jī)制。
/proc 中的大多數(shù)虛擬文件都可以使用cat、more和less等命令查看。其中,/proc/modules列出了所有l(wèi)oad進(jìn)入內(nèi)核的模塊列表,里面的內(nèi)容會隨著系統(tǒng)使用和配置的變化而變化。/proc/modules內(nèi)模塊加載情況查詢?nèi)缦拢?/p>
[root@localhost]# cat /proc/modules
hellomod 16384 0 - Live 0xffffffffc1072000 (OE)
openvswitch 212992 0 - Live 0xffffffffc103d000
nf_conncount 24576 1 openvswitch, Live 0xffffffffc1036000
xt_nat 16384 15 - Live 0xffffffffc1022000
vhost_net 40960 1 - Live 0xffffffffc102b000
vhost 65536 1 vhost_net, Live 0xffffffffc0ea4000
...
intel_uncore 258048 0 - Live 0xffffffffc0d39000
pcspkr 16384 0 - Live 0xffffffffc05ad000
mei_me 57344 0 - Live 0xffffffffc0d2a000
ipmi_ssif 49152 0 - Live 0xffffffffc0d16000
mei 184320 1 mei_me, Live 0xffffffffc0cd8000
i2c_i801 36864 0 - Live 0xffffffffc0c46000
...
#hellomod是小編自定義的模塊,加載后可在/proc/modules中查詢到
[root@localhost]# cat /proc/modules | grep hellomod
hellomod 16384 0 - Live 0xffffffffc1072000 (OE)
上述查詢結(jié)果大家看起來可能會比較懵,接下來讓我們解析下各列的含義:
- 第一列:模塊的名字
- 第二列:模塊的內(nèi)存大小,單位是bytes
- 第三列:被load的次數(shù),0意味著沒有被load過
- 第四列:是否依賴第三方moudle,列出這些module
- 第五列:模塊的狀態(tài),有Live, Loading, Unloading三種狀態(tài)
- 第六列:模塊當(dāng)前的內(nèi)核內(nèi)存偏移位置。這些信息,debug的時候會非常有用。例如使用診斷工具 addr2line時就可能會用到該內(nèi)存偏移位置。
2、lsmod命令
Linux lsmod命令用于顯示已經(jīng)加載到內(nèi)核中的模塊的狀態(tài)信息,原理就是將/proc/modules 中的信息調(diào)整一下格式輸出。
執(zhí)行l(wèi)smod命令后會列出所有已載入系統(tǒng)的模塊,lsmod 輸出列表中有一列 Used by
,它表明此模塊正在被其他模塊使用。Linux操作系統(tǒng)的核心具有模塊化的特性,因此在編譯核心時,無須把全部的功能都放入核心。您可以將這些功能編譯成一個個單獨(dú)的模塊,待需要時再分別載入。
[root@localhost]# lsmod
Module Size Used by
hellomod 16384 0
openvswitch 212992 0
tun 69632 4 vhost_net
bridge 393216 0
...
mei 184320 1 mei_me
i2c_i801 36864 0
ioatdma 69632 0
lpc_ich 28672 0
...
dm_mirror 28672 0
dm_region_hash 28672 1 dm_mirror
dm_log 24576 2 dm_region_hash,dm_mirror
dm_mod 204800 12 dm_log,dm_mirror
#hellomod是小編自定義的模塊,加載后可通過lsmod查詢到
[root@localhost]# lsmod | grep hellomod
hellomod 16384 0
上述查詢結(jié)果雖然比第一種方法輸出列少,但是可能大家依然不知道什么意思,接下來讓我們解析下各列的含義:
- 第一列:模塊的名字
- 第二列:模塊的大小
- 第三列:被其他模塊所依賴的次數(shù)
- 第四列:依賴該模塊的模塊名稱
3、/sys/module 目錄
該目錄下有系統(tǒng)中所有的模塊信息,不論這些模塊是以內(nèi)聯(lián)(inlined) 方式 編譯到內(nèi)核鏡像文件中,還是編譯為外部模塊(.ko),均會在/sys/module目錄下生成以模塊名命名的目錄 。
[root@localhost]# ls -l /sys/module
total 0
drwxr-xr-x. 3 root root 0 Feb 23 19:32 8250
drwxr-xr-x. 3 root root 0 Feb 23 19:32 acpi
drwxr-xr-x. 5 root root 0 Feb 23 19:32 acpi_ipmi
...
drwxr-xr-x. 3 root root 0 Feb 23 19:32 firmware_class
drwxr-xr-x. 5 root root 0 Feb 23 19:32 ghash_clmulni_intel
drwxr-xr-x. 3 root root 0 Feb 23 19:32 gpiolib_acpi
drwxr-xr-x. 5 root root 0 Feb 23 19:32 grace
drwxr-xr-x. 3 root root 0 Feb 23 19:32 haltpoll
drwxr-xr-x. 5 root root 0 Feb 23 19:34 hellomod
drwxr-xr-x. 3 root root 0 Feb 23 19:32 hid
...
[root@localhost]# ls -l /sys/module | grep hellomod
drwxr-xr-x. 5 root root 0 Feb 23 19:34 hellomod
當(dāng)我們加載驅(qū)動程序之后,我們可以通過 調(diào)用cat /proc/modules、lsmod命令或者查看 /sys/module/,查看我們剛加載的模塊有沒加載成功。
二. 內(nèi)核模塊加載與卸載工具
1、insmod
將指定模塊加載到內(nèi)核,insmod命令完全由用戶自行加載一個完整文件名的模塊,不會主動分析模塊依賴性,需要自己手動加載。
語法格式:
insmod [ 文件名 ] [ 模塊參數(shù)... ]
例如:
insmod /path/xxx.ko
其中,path表示ko文件的絕對路徑或相對路徑。
2、depmod
分析可加載模塊的依賴性,生成modules.dep文件和modules.dep.bin文件,以便modprobe加載模塊時根據(jù)modules.dep.bin進(jìn)行依賴模塊加載。
語法格式:
[root@localhost]# depmod [-adeisvV][-m< 文件 >][--help][模塊名稱]
-a 分析所有可用的模塊
-d 執(zhí)行排錯模式
-e 輸出無法參照的符號
-i 不檢查符號表的版本
-m< 文件 > 使用指定的符號表文件
-n 不寫入 modules.dep ,而是將結(jié)果輸出到螢?zāi)簧?standard out);
-s 在系統(tǒng)記錄中記錄錯誤
-v 執(zhí)行時顯示詳細(xì)的信息
-V 顯示版本信息
--help 顯示幫助
Linux內(nèi)核模塊可以為其它模塊提供提供服務(wù)(在代碼中使用EXPORT_SYMBOL),這種服務(wù)被稱作”symbols”。若第二個模塊使用了這個symbol,則該模塊很明顯依賴于第一個模塊。這些依賴關(guān)系是非常繁雜的。
depmod 通過讀取 /lib/modules/$(uname -r) /下的每個模塊并確定它導(dǎo)出的符號和需要的符號,創(chuàng)建一個模塊依賴關(guān)系列表。默認(rèn)情況下,此列表將寫入modules.dep和名為modules.dep.bin的二進(jìn)制哈希版本,這兩個文件位于同一目錄中。如果在命令行中給出了文件名,則只檢查這些模塊(除非列出了所有模塊,否則這些模塊很少有用)。
depmod 還創(chuàng)建由 modules.symbols
文件及其二進(jìn)制散列版本 modules.symbols.bin
中的模塊提供的符號列表。
最后,如果模塊提供了特殊的設(shè)備名(devname),則 depmod 將輸出一個名為 modules.devname
的文件,該設(shè)備名應(yīng)在啟動時填充在 /dev
中(由 udev
等實(shí)用程序填充)。
3、modprobe
加載或卸載內(nèi)核模塊;
語法格式:
modprobe [ 參數(shù)] [模塊名稱] [模塊參數(shù)...]
modprobe需要根據(jù)modules.dep.bin文件的內(nèi)容進(jìn)行加載操作,可以自動解決模塊間的依賴關(guān)系表,一次性將有依賴關(guān)系的驅(qū)動全部加載到內(nèi)核,不需要驅(qū)動的具體地址,但需要將驅(qū)動拷貝或設(shè)置軟鏈接到/lib/modules/$(uname -r)/
或者/lib/modules/$(uname -r)/extra/
目錄下。modprobe加載模塊時并不需要指定ko文件的具體目錄,直接使用modprobe 模塊名字即可,我們不妨測試下:
#加載hellomod.ko模塊之前,默認(rèn)的模塊信息如下
[root@localhost 6.2.0-rc5+]# modinfo hellomod
filename: /lib/modules/6.2.0-rc5+/hellomod.ko
license: Dual BSD/GPL
srcversion: DEA7EE7031439C7A120C77C
depends:
retpoline: Y
name: hellomod
vermagic: 6.2.0-rc5+ SMP preempt mod_unload modversions
#刪除調(diào)/lib/modules/$(uname -r)/目錄下的hellomod軟鏈接
[root@localhost 6.2.0-rc5+]# rm -f hellomod.ko
[root@localhost 6.2.0-rc5+]# ls -l
total 3800
lrwxrwxrwx. 1 root root 27 Feb 20 11:17 build - ?> /usr/src/kernels/6.2.0-rc5+
drwxr-xr-x. 13 root root 141 Feb 24 10:46 kernel
-rw-r--r--. 1 root root 943175 Feb 24 19:26 modules.alias
-rw-r--r--. 1 root root 899138 Feb 24 19:26 modules.alias.bin
-rw-r--r--. 1 root root 8920 Jan 30 10:22 modules.builtin
-rw-r--r--. 1 root root 11118 Feb 24 19:26 modules.builtin.bin
-rw-r--r--. 1 root root 69179 Jan 30 10:22 modules.builtin.modinfo
-rw-r--r--. 1 root root 313395 Feb 24 19:26 modules.dep
-rw-r--r--. 1 root root 429116 Feb 24 19:26 modules.dep.bin
-rw-r--r--. 1 root root 405 Feb 24 19:26 modules.devname
-rw-r--r--. 1 root root 106408 Jan 30 10:22 modules.order
-rw-r--r--. 1 root root 833 Feb 24 19:26 modules.softdep
-rw-r--r--. 1 root root 494353 Feb 24 19:26 modules.symbols
-rw-r--r--. 1 root root 593333 Feb 24 19:26 modules.symbols.bin
lrwxrwxrwx. 1 root root 27 Feb 20 11:17 source - ?> /usr/src/kernels/6.2.0-rc5+
#復(fù)制源文件路徑下的hellomod.ko到/lib/modules/$(uname -r)路徑下
[root@localhost 6.2.0-rc5+]# cp /tmp/28/hellomod.ko .
[root@localhost