經過兩周的摸索,終於對Linux裝置驅動開發有了個初步的認識,下面對Linux裝置驅動開發環境的搭建做個小結,以方便自己以後查詢,同時也能給同道的初學者一點協助。
剛接觸Linux裝置驅動時,初學者往往連如何編譯驅動程式都不懂,更別說編譯進核心或載入測試了。一般都是在網上找個最簡單的 helloworld驅動程式,然後嚴格按照網上所說的步驟編譯,結果卻得到一大堆見都沒見過的錯誤,更不要說根據錯誤資訊來解決問題了,很多人到這裡就 不知道如何往下進行了。十幾天前我也卡在這裡很長時間,現在知道所以然了就記下來,些許對一些同道者有協助。
一個基本的Linux裝置驅動開發環境由宿主機和目標機組成,宿主機就是用來做驅動開發工作的主機,目標機就是用來運行和測試裝置驅動的主機,在宿 主機上需要有開發工具(gcc,gdb,make等)和linux源碼(版本要對應目標機上的linux核心),而目標機上只要運行linux即可。由於 步驟有所不同,下面分為普通Linux裝置驅動開發和嵌入式Linux設別驅動開發兩種情況來講述環境的搭建和驅動程式的編譯:
(一)普通Linux裝置驅動開發
普通Linux主要是區分於嵌入式Linux(一般指uClinux),在這種開發中宿主機和目標機可以是一台主機,即在本機上開發編譯然後在本機 上載入運行(Linux裝置驅動也可以直接編譯進核心,但為了開發工作方便,一般採用動態載入的方式),當然也可以是兩台主機,如果是兩台主機的話,要保 證宿主機上的linux源碼的版本號碼與目標機中的linux核心版本一致。普通Linux裝置驅動開發的步驟如下:
- 在宿主機上安裝開發工具和下載linux源碼(要求版本號碼和目標機上的linux核心版本一致)。開發工具主要有gcc、gdb、make等,這些工具在redhat或fc中預設就安裝了,在debian或Ubuntu中可以通過下面這個命令安裝:
apt-get install build-essential
linux源碼可以通過以下幾種途徑獲得:
- 直接去www.kernel.org下載
- 通過包管理工具下載源碼,在debian和Ubuntu中可以通過下面這個命令下載,
apt-get install linux-source-(版本號碼)
,下載後的檔案在/usr/src目錄中,解壓到該目錄即可
將源碼解壓到/usr/src/目錄後,進入linux-source-(版本號碼)目錄中執行下面幾個命令:
make oldconfig
make prepare
make scripts
- 編寫Linux驅動程式,以一個最簡單的hello.c為例,hello.c的內容如下:
#include "linux/init.h"
#include "linux/module.h"
static int hello_init(void)
{
printk(KERN_ALERT "Hello World linux_driver_module\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "Goodbey linux_driver_module\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("lpj");
- 寫Makefile檔案,一個樣本如下,裡面各項參數根據實際情況更改:
#sample driver module
obj-m := hello.o
KDIR = /usr/src/linux-source-2.6.24/
all:
$(MAKE) -C $(KDIR) M=$(PWD)
.PHONY:clean
clean:
rm -f *.mod.c *.mod.o *.ko *.o *.tmp_versions
- 編譯,在hello.c和Makefile所在目錄下執行 make 即可,編譯後在目前的目錄產生hello.ko檔案
- 載入並測試:載入使用insmod或modprobe命令來實現,如在當前路徑執行如下代碼:
insmod hello.ko 或 modprobe hello
注意,如果在虛擬終端載入核心的話,將看不到核心列印資訊,因為核心列印資訊不會輸出到虛擬終端,而是輸出到/proc/kmsg檔案中,所以可以通過以下方式查看核心資訊:
cat /proc/kmsg
會一直列印,需要Ctrl-C手動終止
dmesg 或 dmesg | tail -N
,N為一數字,表示顯示最後N行
- 卸載:使用rmmod命令卸載驅動模組,如
rmmod hello
(二)嵌入式Linux裝置驅動開發
這種開發中一般目標機為帶有嵌入式處理器的開發板,而宿主機為PC,開發環境需要在宿主機上搭建,嵌入式Linux裝置驅動開發的步驟如下:
- 在宿主機上下載嵌入式Linux的源碼,並安裝嵌入式Linux開發工具(針對於不同的嵌入式處理器,工具也有所不同,如對應於Arm的arm-gcc系列,針對nios2處理器的nios2-cc系列)
- 編寫Linux裝置驅動驅動程式,還以上面給出的hello.c為例,將該檔案複製到(linux 源碼目錄)/drivers/(目標檔案夾)/中
- 在(目標檔案夾)中建立Makefile和Kconfig(菜單設定檔),內容分別如下:
#makefile
obj-$(CONFIG_HELLODRV) += hello.o
#Kconfig
menu USER_DEVICE_DRIVERS
config HELLODRV
tristate "Hello"
---help---
This is a sample driver programme.
endmenu
注意,如果Kconfig檔案中的"tristate"寫成"bool",則該模組只能選為Y(編譯進核心)或N(不選擇),不能選為M(編譯為模組,可動態載入)
- 修改上層目錄( linux核心源碼目錄/drivers/)中的Makefile和Kconfig檔案,Makefile中加入如下語句:
#makefile
obj-y += (目標檔案夾)
(此處有多種寫法,這隻是其中一種)
Kconfig中加入如下語句:
#Kconfig
source "drivers/(目標檔案夾)/Kconfig"
- 編譯核心:幾個基本的命令及選擇介面如下:
make menuconfig
執行到這一步後,會看到下面這個介面:
其中Vendor/Product...是選擇處理器廠家和型號的,Kernel/Library...是配置應用程式的,按空格鍵或斷行符號鍵可以進入選項進行配置,用上下鍵移動到Kernel/Library...菜單上,按空格或斷行符號進入下面的核心配置介面:
在該介面有兩個Customize...選項,第一個是選擇自訂配置核心,第二個是選擇自訂配置應用程式,按空格鍵可以選擇這些選項,選擇後按 exit鍵退出,選擇是否儲存的時候選擇“yes“,如果選擇了第一個Customize...,則退出後會自動進入核心配置介面,如:
該介面有很多選項,這裡不細講,我們要配置驅動模組,就用上下鍵移動到Device Drivers上,然後按斷行符號或空格鍵進入,裝置驅動配置介面如:
這裡就是linux-2.X/drivers/Kconfig裡的內容了,下面那個綠色的V(+)表示這一頁沒顯示完,可以用下鍵繼續往下瀏覽,找到我們自己的菜單名,然後按斷行符號或空格進入,我的模組配置介面如下:
用M鍵使選項前的角括弧裡顯示M表示該模組要動態載入,也可以按y鍵選擇直接編輯進核心,選擇完後exit退出,選擇yes或no的對話方塊通一選yes。
make romfs
#第一次編譯核心前一定要有該步驟
make
- 載入測試:將產生的zImage檔案下載到開發板,開發板上的嵌入式Linux啟動後可以用insmod或modprobe載入驅動模組,測試完畢後可以通過rmmod命令卸載驅動模組