Linux提供了三種方法查詢加載到內(nèi)核的模塊,一種方法是直接訪問proc虛擬文件系統(tǒng)獲取,一種方法則是比較常用的lsmod方法獲取,而lsmod的輸出其實(shí)是基于/proc/modules。另外還有一種就是查看/sys/module/目錄下是否生成已加載模塊的目錄。
Linux 內(nèi)核提供了一種通過 /proc 文件系統(tǒng),在運(yùn)行時(shí)訪問內(nèi)核內(nèi)部數(shù)據(jù)結(jié)構(gòu)、改變內(nèi)核設(shè)置的機(jī)制。
(相關(guān)資料圖)
/proc 中的大多數(shù)虛擬文件都可以使用cat、more和less等命令查看。其中,/proc/modules列出了所有l(wèi)oad進(jìn)入內(nèi)核的模塊列表,里面的內(nèi)容會(huì)隨著系統(tǒng)使用和配置的變化而變化。/proc/modules內(nèi)模塊加載情況查詢?nèi)缦拢?/p>
[root@localhost]# cat /proc/moduleshellomod 16384 0 - Live 0xffffffffc1072000 (OE)openvswitch 212992 0 - Live 0xffffffffc103d000nf_conncount 24576 1 openvswitch, Live 0xffffffffc1036000xt_nat 16384 15 - Live 0xffffffffc1022000vhost_net 40960 1 - Live 0xffffffffc102b000vhost 65536 1 vhost_net, Live 0xffffffffc0ea4000...intel_uncore 258048 0 - Live 0xffffffffc0d39000pcspkr 16384 0 - Live 0xffffffffc05ad000mei_me 57344 0 - Live 0xffffffffc0d2a000ipmi_ssif 49152 0 - Live 0xffffffffc0d16000mei 184320 1 mei_me, Live 0xffffffffc0cd8000i2c_i801 36864 0 - Live 0xffffffffc0c46000...#hellomod是小編自定義的模塊,加載后可在/proc/modules中查詢到[root@localhost]# cat /proc/modules | grep hellomodhellomod 16384 0 - Live 0xffffffffc1072000 (OE)
上述查詢結(jié)果大家看起來可能會(huì)比較懵,接下來讓我們解析下各列的含義:
第一列:模塊的名字第二列:模塊的內(nèi)存大小,單位是bytes第三列:被load的次數(shù),0意味著沒有被load過第四列:是否依賴第三方moudle,列出這些module第五列:模塊的狀態(tài),有Live, Loading, Unloading三種狀態(tài)第六列:模塊當(dāng)前的內(nèi)核內(nèi)存偏移位置。這些信息,debug的時(shí)候會(huì)非常有用。例如使用診斷工具 addr2line時(shí)就可能會(huì)用到該內(nèi)存偏移位置。Linux lsmod命令用于顯示已經(jīng)加載到內(nèi)核中的模塊的狀態(tài)信息,原理就是將/proc/modules 中的信息調(diào)整一下格式輸出。
執(zhí)行l(wèi)smod命令后會(huì)列出所有已載入系統(tǒng)的模塊,lsmod 輸出列表中有一列 Used by
,它表明此模塊正在被其他模塊使用。Linux操作系統(tǒng)的核心具有模塊化的特性,因此在編譯核心時(shí),無須把全部的功能都放入核心。您可以將這些功能編譯成一個(gè)個(gè)單獨(dú)的模塊,待需要時(shí)再分別載入。
[root@localhost]# lsmodModule Size Used byhellomod 16384 0openvswitch 212992 0tun 69632 4 vhost_netbridge 393216 0...mei 184320 1 mei_mei2c_i801 36864 0ioatdma69632 0lpc_ich 28672 0...dm_mirror 28672 0dm_region_hash 28672 1 dm_mirrordm_log 24576 2 dm_region_hash,dm_mirrordm_mod 204800 12 dm_log,dm_mirror#hellomod是小編自定義的模塊,加載后可通過lsmod查詢到[root@localhost]# lsmod | grep hellomodhellomod 16384 0
上述查詢結(jié)果雖然比第一種方法輸出列少,但是可能大家依然不知道什么意思,接下來讓我們解析下各列的含義:
第一列:模塊的名字第二列:模塊的大小第三列:被其他模塊所依賴的次數(shù)第四列:依賴該模塊的模塊名稱該目錄下有系統(tǒng)中所有的模塊信息,不論這些模塊是以內(nèi)聯(lián)(inlined) 方式 編譯到內(nèi)核鏡像文件中,還是編譯為外部模塊(.ko),均會(huì)在/sys/module目錄下生成以模塊名命名的目錄 。
[root@localhost]# ls -l /sys/moduletotal 0drwxr-xr-x. 3 root root 0 Feb 23 19:32 8250drwxr-xr-x. 3 root root 0 Feb 23 19:32 acpidrwxr-xr-x. 5 root root 0 Feb 23 19:32 acpi_ipmi...drwxr-xr-x. 3 root root 0 Feb 23 19:32 firmware_classdrwxr-xr-x. 5 root root 0 Feb 23 19:32 ghash_clmulni_inteldrwxr-xr-x. 3 root root 0 Feb 23 19:32 gpiolib_acpidrwxr-xr-x. 5 root root 0 Feb 23 19:32 gracedrwxr-xr-x. 3 root root 0 Feb 23 19:32 haltpolldrwxr-xr-x. 5 root root 0 Feb 23 19:34 hellomoddrwxr-xr-x. 3 root root 0 Feb 23 19:32 hid...[root@localhost]# ls -l /sys/module | grep hellomoddrwxr-xr-x. 5 root root 0 Feb 23 19:34 hellomod
當(dāng)我們加載驅(qū)動(dòng)程序之后,我們可以通過 調(diào)用cat /proc/modules、lsmod命令或者查看 /sys/module/,查看我們剛加載的模塊有沒加載成功。
將指定模塊加載到內(nèi)核,insmod命令完全由用戶自行加載一個(gè)完整文件名的模塊,不會(huì)主動(dòng)分析模塊依賴性,需要自己手動(dòng)加載。
語法格式:
insmod [ 文件名 ] [ 模塊參數(shù)... ]
例如:
insmod /path/xxx.ko
其中,path表示ko文件的絕對(duì)路徑或相對(duì)路徑。
分析可加載模塊的依賴性,生成modules.dep文件和modules.dep.bin文件,以便modprobe加載模塊時(shí)根據(jù)modules.dep.bin進(jìn)行依賴模塊加載。
語法格式:
[root@localhost]# depmod [-adeisvV][-m< 文件 >][--help][模塊名稱]-a 分析所有可用的模塊-d 執(zhí)行排錯(cuò)模式-e 輸出無法參照的符號(hào)-i 不檢查符號(hào)表的版本-m< 文件 > 使用指定的符號(hào)表文件-n 不寫入 modules.dep ,而是將結(jié)果輸出到螢?zāi)簧?standard out);-s 在系統(tǒng)記錄中記錄錯(cuò)誤-v 執(zhí)行時(shí)顯示詳細(xì)的信息-V 顯示版本信息--help 顯示幫助
Linux內(nèi)核模塊可以為其它模塊提供提供服務(wù)(在代碼中使用EXPORT_SYMBOL),這種服務(wù)被稱作”symbols”。若第二個(gè)模塊使用了這個(gè)symbol,則該模塊很明顯依賴于第一個(gè)模塊。這些依賴關(guān)系是非常繁雜的。
depmod 通過讀取 /lib/modules/$(uname -r) /下的每個(gè)模塊并確定它導(dǎo)出的符號(hào)和需要的符號(hào),創(chuàng)建一個(gè)模塊依賴關(guān)系列表。默認(rèn)情況下,此列表將寫入modules.dep和名為modules.dep.bin的二進(jìn)制哈希版本,這兩個(gè)文件位于同一目錄中。如果在命令行中給出了文件名,則只檢查這些模塊(除非列出了所有模塊,否則這些模塊很少有用)。
depmod 還創(chuàng)建由 modules.symbols
文件及其二進(jìn)制散列版本 modules.symbols.bin
中的模塊提供的符號(hào)列表。
最后,如果模塊提供了特殊的設(shè)備名(devname),則 depmod 將輸出一個(gè)名為 modules.devname
的文件,該設(shè)備名應(yīng)在啟動(dòng)時(shí)填充在 /dev
中(由 udev
等實(shí)用程序填充)。
加載或卸載內(nèi)核模塊;
語法格式:
modprobe [ 參數(shù)] [模塊名稱] [模塊參數(shù)...]
modprobe需要根據(jù)modules.dep.bin文件的內(nèi)容進(jìn)行加載操作,可以自動(dòng)解決模塊間的依賴關(guān)系表,一次性將有依賴關(guān)系的驅(qū)動(dòng)全部加載到內(nèi)核,不需要驅(qū)動(dòng)的具體地址,但需要將驅(qū)動(dòng)拷貝或設(shè)置軟鏈接到/lib/modules/$(uname -r)/
或者/lib/modules/$(uname -r)/extra/
目錄下。modprobe加載模塊時(shí)并不需要指定ko文件的具體目錄,直接使用modprobe 模塊名字即可,我們不妨測(cè)試下:
#加載hellomod.ko模塊之前,默認(rèn)的模塊信息如下[root@localhost 6.2.0-rc5+]# modinfo hellomodfilename: /lib/modules/6.2.0-rc5+/hellomod.kolicense: Dual BSD/GPLsrcversion: DEA7EE7031439C7A120C77Cdepends:retpoline: Yname: hellomodvermagic: 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 -ltotal 3800lrwxrwxrwx. 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.binlrwxrwxrwx. 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 6.2.0-rc5+]# ls -ltotal 4080lrwxrwxrwx. 1 root root 27 Feb 20 11:17 build - > /usr/src/kernels/6.2.0-rc5+-rw-r--r--. 1 root root 285744 Feb 25 17:18 hellomod.kodrwxr-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.binlrwxrwxrwx. 1 root root 27 Feb 20 11:17 source - > /usr/src/kernels/6.2.0-rc5+#直接執(zhí)行modprobe會(huì)報(bào)錯(cuò)并提示無法插入hellomod.ko文件,需要執(zhí)行depmod命令更新modules.dep和modules.dep.bin文件,#將hellomod.ko的路徑寫入modules.dep和modules.dep.bin文件中[root@localhost 6.2.0-rc5+]# modprobe hellomodmodprobe: ERROR: could not insert "hellomod": Unknown symbol in module, or unknown parameter (see dmesg)[root@localhost 6.2.0-rc5+]##depmod指令會(huì)自動(dòng)分析/lib/modules/$(uname -r)/目錄下的可加載模塊,并按照固定的格式填入modules.dep和modules.dep.bin中。#因此,我們可以先將需要加載的ko文件拷貝到對(duì)應(yīng)的目錄,再執(zhí)行depmod指令。[root@localhost 6.2.0-rc5+]# depmod#執(zhí)行depmod后,在modules.dep和modules.dep.bin中已經(jīng)存在有我們需要加載的ko文件名了,注意,不要手工的去編輯modules.dep文件[root@localhost 6.2.0-rc5+]# cat modules.dep | grep hellomodhellomod.ko:#再執(zhí)行modprobe指令,即可加載模塊了,modprobe是根據(jù)modules.dep.bin文件中的路徑信息加載ko文件。[root@localhost 6.2.0-rc5+]# modprobe hellomod[root@localhost 6.2.0-rc5+]# lsmod | grep hellomodhellomod 16384 0
注意:在加載自己制作的ko文件時(shí),我們最好使用insmod命令;因?yàn)閙odprobe使用的模塊加載路徑一般是系統(tǒng)啟動(dòng)時(shí)的默認(rèn)加載路徑,存放的一般是系統(tǒng)原始的ko文件。
如果要使用modprobe進(jìn)行加載,則建議不用將默認(rèn)加載路徑下的模塊文件替換掉,一旦將原始ko模塊文件替換掉,假如自己制作的模塊文件存在bug,可能導(dǎo)致系統(tǒng)出現(xiàn)故障,即使重新啟動(dòng)機(jī)器,系統(tǒng)默認(rèn)加載的仍然是自己制作的ko文件,這時(shí)就會(huì)導(dǎo)致系統(tǒng)無法正常啟動(dòng)。因此,假如要使用modprobe命令,則建議在與默認(rèn)加載路徑不同的
/lib/modules/$(uname -r)/
或者/lib/modules/$(uname -r)/extra/
路徑下生成源模塊文件的軟鏈接,再分別執(zhí)行depmod, modprobe xxx兩個(gè)命令,這樣能成功加載自己制作的模塊文件,且即使自制模塊有bug也不影響系統(tǒng)重啟后成功啟動(dòng)。因?yàn)檫@樣操作過后,系統(tǒng)重啟后該模塊文件未加載到內(nèi)核,讀者可以自己實(shí)驗(yàn)。由上述可知,無論使用modprobe或者insmod加載自制的模塊,在重啟后均會(huì)失效;對(duì)于insmod,系統(tǒng)重啟后仍然會(huì)加載默認(rèn)路徑下的內(nèi)核模塊。對(duì)于modprobe,系統(tǒng)重啟后則既不會(huì)加載自制模塊也不會(huì)加載默認(rèn)模塊。
好多文章或博客里面寫到modprobe是根據(jù)modules.dep文件的內(nèi)容進(jìn)行加載模塊操作的,其實(shí)是不正確的。使用 strace 追蹤 modprobe 的調(diào)用過程,發(fā)現(xiàn) modprobe 并不會(huì)使用 modules.dep 文件,而是調(diào)用modules.dep.bin文件。
strace 的相關(guān)信息記錄如下:
[root@localhost]# strace /sbin/modprobe hellomod 2 >&1 | grep "modules"open("/lib/modules/6.2.0-rc5+/modules.softdep", O_RDONLY|O_CLOEXEC) = 3open("/lib/modules/6.2.0-rc5+/modules.dep.bin", O_RDONLY|O_CLOEXEC) = 3open("/lib/modules/6.2.0-rc5+/modules.alias.bin", O_RDONLY|O_CLOEXEC) = 3open("/lib/modules/6.2.0-rc5+/modules.symbols.bin", O_RDONLY|O_CLOEXEC) = 3open("/lib/modules/6.2.0-rc5+/modules.builtin.bin", O_RDONLY|O_CLOEXEC) = 3open("/lib/modules/6.2.0-rc5+/hellomod.ko", O_RDONLY|O_CLOEXEC) = 3
由上面結(jié)果可知,modprobe在加載模塊時(shí),它訪問了 modules.dep.bin、modules.alias.bin、modules.symbols.bin、modules.builtin.bin 等文件,它并沒有訪問 modules.dep 文件。
接下來讓我們使用man modules.dep看下有關(guān)該文件的說明:
DESCRIPTION modules.dep.bin is a binary file generated by depmod listing the dependencies for every module in the directories under /lib/modules/version. It is used by kmod tools such as modprobe and libkmod. Its text counterpar is located in the same directory with the name modules.dep. The text version is maintained only for easy of reading by humans and is in no way used by any kmod tool. These files are not intended for editing or use by any additional utilities as their format is subject to change in the future. You should use the modinfo(8) command to obtain information about modules in a future proof and compatible fashion rather than touching these files.
從man的描述來看,modules.dep 只是供人查看的,kmod 相關(guān)的命令使用的是 modules.dep.bin 這個(gè)文件,如modprobe和libkmod。
查看某個(gè)模塊的詳細(xì)信息。
語法格式:
[root@localhost]# modinfo [-adlpn0Fkbvh] < 模塊文件 >-a 或–author 顯示模塊開發(fā)人員。-d 或–description 顯示模塊的說明。-l 或—license 顯示版本信息-p 或–parameters 顯示模塊所支持的參數(shù)。-0 或–null 用 \\0 代替 \\n -F 或–field=FIELD 僅打印提供的字段-k 或–set-version=VERSION 用 VERSION 代替uname -r-b 或–basedir=DIR 使用 DIR 作為/lib/modules 的文件系統(tǒng)根目錄-V 或–version 顯示版本信息-h 或–help 顯示幫助信息
modinfo命令通過/lib/modules/$(uname -r)/modules.dep
文件獲取模塊(ko文件)的實(shí)際存放路徑,之后,通過調(diào)用modinfo()函數(shù)打開模塊(ko文件)從而獲取模塊的詳細(xì)信息并打印出來。因此,存在這樣一種情況,即模塊實(shí)際并未加載,但是通過modinfo卻可以讀取到模塊的詳細(xì)信息。
注:這就告誡我們,當(dāng)使用modinfo讀出模塊的詳細(xì)信息時(shí),不要就誤以為模塊已加載到內(nèi)核。
這里,我們演示一下模塊未加載,但是modinfo卻能顯示模塊的詳細(xì)信息的例子,如下:
#lsmod顯示的內(nèi)容中未檢索到hellomod模塊,說明hellomod模塊未加載到內(nèi)核[root@localhost]# lsmod | grep hellomod[root@localhost]##直接執(zhí)行modinfo命令可以顯示hellomod模塊的詳細(xì)信息[root@localhost]# modinfo hellomodfilename: /lib/modules/6.2.0-rc5+/hellomod.kolicense: Dual BSD/GPLsrcversion: DEA7EE7031439C7A120C77Cdepends:retpoline: Yname: hellomodvermagic: 6.2.0-rc5+ SMP preempt mod_unload modversions[root@localhost]##查看/lib/modules/$(uname -r)/modules.dep文件內(nèi)容,包含hellomod路徑[root@localhost]# cat /lib/modules/$(uname -r)/modules.dep | grep hellomodhellomod.ko:[root@localhost]# ls -l /lib/modules/$(uname -r)total 3800lrwxrwxrwx. 1 root root 27 Feb 20 11:17 build - > /usr/src/kernels/6.2.0-rc5+lrwxrwxrwx. 1 root root 19 Feb 23 19:26 hellomod.ko - > /tmp/28/hellomod.kodrwxr-xr-x. 13 root root 141 Feb 24 10:46 kernel-rw-r--r--. 1 root root 943175 Feb 24 14:17 modules.alias-rw-r--r--. 1 root root 899138 Feb 24 14:17 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 14:17 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 14:17 modules.dep-rw-r--r--. 1 root root 429116 Feb 24 14:17 modules.dep.bin-rw-r--r--. 1 root root 405 Feb 24 14:17 modules.devname-rw-r--r--. 1 root root 106408 Jan 30 10:22 modules.order-rw-r--r--. 1 root root 833 Feb 24 14:17 modules.softdep-rw-r--r--. 1 root root 494353 Feb 24 14:17 modules.symbols-rw-r--r--. 1 root root 593333 Feb 24 14:17 modules.symbols.binlrwxrwxrwx. 1 root root 27 Feb 20 11:17 source - > /usr/src/kernels/6.2.0-rc5+
上面示例說明,hellomod模塊未加載時(shí),modinfo通過讀取modules.dep文件中hellomod模塊的實(shí)際路徑,找到hellomod.ko文件,讀取該文件,從而獲取hellomod模塊的詳細(xì)信息。
接下來,我們通過modprobe加載hellomod模塊,再通過modinfo查看,發(fā)現(xiàn)和未加載hellomod模塊時(shí)顯示的一樣。
[root@localhost]# modprobe hellomod[root@localhost]# lsmod | grep hellomodhellomod 16384 0[root@localhost]# modinfo hellomodfilename: /lib/modules/6.2.0-rc5+/hellomod.kolicense: Dual BSD/GPLsrcversion: DEA7EE7031439C7A120C77Cdepends:retpoline: Yname: hellomodvermagic: 6.2.0-rc5+ SMP preempt mod_unload modversions[root@localhost]#
注:modinfo只有在其后接xxx.ko時(shí),才是讀取該模塊的詳細(xì)信息,即只有帶.ko后綴時(shí),讀取的才是當(dāng)前路徑下的模塊文件;不帶.ko后綴時(shí),讀取的則是
/lib/modules/$(uname -r)/modules.dep
文件內(nèi)保存的路徑下的模塊的信息。
rmmod命令來自于英文詞組”remove module“的縮寫,其功能是用于移除內(nèi)核中已加載的模塊。
語法格式:
rmmod [參數(shù)] 模塊名稱
常用參數(shù)如下:
-a | 刪除所有目前不需要的模塊 |
---|---|
-s | 把信息輸出至日志服務(wù)中 |
-v | 顯示指令執(zhí)行的詳細(xì)信息 |
-f | 強(qiáng)制移除模塊 |
-w | 確認(rèn)模塊能被刪除時(shí)再操作 |
[root@localhost 6.2.0-rc5+]# lsmod | grep hellomodhellomod 16384 0[root@localhost 6.2.0-rc5+]#[root@localhost 6.2.0-rc5+]# rmmod hellomod[root@localhost 6.2.0-rc5+]# lsmod | grep hellomod[root@localhost 6.2.0-rc5+]##查看dmesg日志,可以看到hellomod模塊在卸載后的日志[root@localhost ~]# dmesg | tail -2[181935.423616] Hello, World![181944.217893] Goodbye, World!
標(biāo)簽: