Linux模組編程
1.1 模組學習什麼
1.認識什麼是模組。跟我學習的驅動有什麼關係。
2.熟悉模組的安裝,卸載,查看
3.熟悉模組的基本架構
4.熟悉模組的編程方法 1.2 核心模組概述
Linux 核心的整體結構非常龐大,其包含的組件也非常多。我們怎樣把需要的部分都包含在核心中呢。一種方法是把所有需要的功能都編譯到 Linux 核心。這會導致兩個問題,一是產生的核心會很大,二是如果我們要在現有的核心中新增或刪除功能,將不得不重新編譯核心。
有沒有一種機制使得編譯出的核心本身並不需要包含所有功能,而在這些功能需要被使用的時候,其對應的代碼可被動態地載入到核心中呢。
Linux 提供了這樣的一種機制,這種機制被稱為模組(Module),可以實現以上效果。模組具有以下特點。
1.模組本身不被編譯入核心映像,從而控制了核心的大小。
2.模組一旦被載入,它就和核心中的其他部分完全一樣。 1.3 認識模組
我們在配置核心的時候,在配置菜單看到有一種選項可以選擇為<M> <*> < > 。
其中,<M>表示編譯成模組,即modules,這個便於選項編譯的代碼不編譯進核心zImage,而是編譯成一個單獨的檔案,通常為尾碼.ko(2.6以上核心版本是.ko,2.6核心之前是.o)檔案,那麼我們可以像軟體一樣選擇安裝和卸載這些.ko模組檔案。
<*>表示編譯進核心,就是將這一段模組代碼編譯到了zImage鏡像檔案去了,在核心啟動的時候自動安裝執行我們的模組代碼,這樣做類似於一些安裝系統的時候內建的驅動,在安裝系統的時候就已經安裝好了。
< > 表示沒有選擇,不做任何事情。
所以,我們所說的模組就是linux下的那些.ko檔案。 1.3.1 tiny4412提供的模組測試程式
在我們學習的Tiny4412提供的 Linux3.5 源碼中有一項模組測試選項,如下:
Tiny4412module sample.
Symbol:TINY4412_HELLO_MODULE [=m]
Type: tristate
Prompt:Tiny4412 module sample
Definedat drivers/char/Kconfig:49
Dependson: ARCH_EXYNOS4 [=y]
Location:
-> DeviceDrivers
->Character devices
注意:因為有依賴項,所以它的依賴必須被選上,即ARCH_EXYNOS4 [=y]。
CONFIG_ARCH_EXYNOS4:
Samsung EXYNOS4 SoCs based systems
Symbol: ARCH_EXYNOS4[=y]
Type :boolean
Prompt: SAMSUNGEXYNOS4
Defined at arch/arm/mach-exynos/Kconfig:14
Depends on: ARCH_EXYNOS [=y]
Location:
-> SystemType
-> SAMSUNGEXYNOS SoCs Support
Selects: HAVE_SMP [=y] && MIGHT_HAVE_CACHE_L2X0 [=y]
這個測試檔案在drivers/char/目錄下的tiny4412_hello_moduls.c。當把它選擇為<M>之後,編譯就會在同級目錄下產生.ko檔案。
編譯命令:make modules
在 Linux 系統中,幾乎所有驅動都可以編譯模組的形式。
總之,模組代碼我們可以在系統啟動後再安裝(zImage檔案中並不包含該選項對應的C代碼)。也可以編譯到核心,像核心配置菜單中選擇為y的選項,對應的C代碼會被編譯到zImage檔案中。
這裡記住一句話:linux下模組不一定是驅動,但是驅動肯是一種模組。
樣本:編譯成模組
1)在linux核心核心配置菜單makememuconfig上把模組測試選項為M,然後退出儲存。
2)編譯成模組,如下:
[root@localhost linux-3.5]# make modules
scripts/kconfig/conf--silentoldconfig Kconfig
CHK include/linux/version.h
CHK include/generated/utsrelease.h
make[1]: “include/generated/mach-types.h”是最新的。
CALL scripts/checksyscalls.sh
CC [M] crypto/ansi_cprng.o
CC [M] drivers/char/tiny4412_hello_module.o
CC [M] drivers/scsi/scsi_wait_scan.o
Building modules, stage 2.
MODPOST 3 modules
CC crypto/ansi_cprng.mod.o
LD [M] crypto/ansi_cprng.ko
CC drivers/char/tiny4412_hello_module.mod.o
LD [M] drivers/char/tiny4412_hello_module.ko
CC drivers/scsi/scsi_wait_scan.mod.o
LD [M] drivers/scsi/scsi_wait_scan.ko
[root@localhost linux-3.5]#
以上就會在drivers/char/產生了tiny4412_hello_module.ko檔案。
然後我們可以查看一下它的存在:
[root@localhost linux-3.5]# cd drivers/char/
[root@localhost char]# ls tiny4412_hello_module.ko -l
-rw-r--r--. 1root root 29062 9月 25 11:26 tiny4412_hello_module.ko
[root@localhost char]#
有了.ko檔案,那麼我們可在以外部獨立的來載入到核心,怎麼載入呢。又怎麼卸載呢。
Linux系統提供專業的命令來完成這樣的事情,下面來介紹這幾個命令。 1.3.2 Linux模組安裝,卸載,查看
Linux下模組提供有安裝,卸載,查看安裝了那個模組以及查看模組資訊等命令。 1.3.1、模組相關命令
| insmod <file name.ko> |
安裝模組進核心 |
| rmmod <file name> |
卸載指定的模組 |
| lsmod |
查看當前系統安裝了哪些模組 |
| modinfo <file name> |
查看模組資訊 |
1.insmod -- 安裝模組
樣本:
[root@JUNJIA /home]# insmod tiny4412_hello_module.ko
[ 140.030000] Hello, Tiny4412 module is installed !
[root@JUNJIA /home]# 2.lsmod -- 列出當前系統已經安裝的模組及模組間的依賴關係(不包含被編譯的核心的模組代碼)
樣本:
[root@JUNJIA /home]# lsmod
tiny4412_hello_module 773 0 - Live 0xbf000000
第1列:模組名
第2列:模組大小
第3列:被引用多少次(本模組的代碼被多少個模組調用)
第4列:被哪個模組引用
說明:
lsmod 命令實際上讀取並分析/proc/modules檔案。
在安裝模組的時候我們可能會遇到這樣的問題,模組版本和要裝的linux核心版本不同會出現問題。
比如我修改了編譯模組的核心版本號碼,然後編譯查看模組資訊:
[root@localhostlinux-3.5]# modinfo drivers/char/tiny4412_hello_module.ko
filename: drivers/char/tiny4412_hello_module.ko
license: GPL
depends:
intree: Y
vermagic: 3.5.0-FriendlyARM_JUNJIASMP preempt mod_unload ARMv7 p2v8
[root@localhostlinux-3.5]#
安裝會出現以下問題:
[root@JUNJIA/home]# insmod tiny4412_hello_module.ko
[3212.730000] tiny4412_hello_module: version magic '3.5.0-FriendlyARM_JUNJIASMP preempt mod_unload ARMv7 p2v8 ' should be '3.5.0-FriendlyARMSMP preempt mod_unload ARMv7 p2v8 '
insmod:can't insert 'tiny4412_hello_module.ko': invalid module format
[root@JUNJIA/home]#
這個錯誤是說模組 版本號碼是3.5.0-FriendlyARM_JUNJIA,而核心版本號碼是3.5.0-FriendlyARM,不匹配不能進行載入。那麼我就只能
結論:模組版本和核心版本不同是不能安裝模組的。
3.rmmod -- 卸載模組(編譯在核心的模組代碼不可以移除)
樣本:
[root@JUNJIA /home]# rmmodtiny4412_hello_module.ko
[root@JUNJIA /home]# lsmod
tiny4412_hello_module 773 0 - Live 0xbf000000 (O) //發現沒有卸載掉
[root@JUNJIA /home]# rmmodtiny4412_hello_module //不加尾碼
[ 231.660000] Good-bye, Tiny4412 module was removed! //列印卸載函數裡的資訊
rmmod: module 'tiny4412_hello_module' not found//這個提示是busybos存在的BUG
[root@JUNJIA /home]#
注意:使用就一些的busybox製作的根檔案系統的rmmod命令不能帶副檔名,帶了不能卸載;但是X86是可以帶的,也可以不帶。現在的新版本根檔案系統製作工具busybox修複了這個功能,帶.ko也能卸載。
有時候我們在卸載模組會遇到出錯等問題,下面是一個常見的問題。
如果busybox下makemenuconfig配置如下:
Symbol:MODPROBE_SMALL [=y]
Prompt:Simplified modutils
Definedat modutils/Config.in:15
Location:
->Linux Module Utilities