近期做的工作主要有兩個,一是將dvsdk_4中的video_copy項目移植到自己的板子上,在參考資料極其匱乏的情況下,本人繼續發揚艱苦奮鬥的作風和打不死的小強精神,終於將Omap3530中的DSP成功地跑起來了。另一個工作就是開始學習Linux裝置驅動開發,為編寫新裝置的驅動做準備。dvsdk的內容比較龐雜,所做的工作還在整理之中,後面我會發出來。Linux裝置驅動開發的資料很多,我只是將我自己所做的工作記錄下來,供和我一樣的初學者參考,以後再回來查看的時候也方便一些。文中不足之處還請大家多多指點~~
Linux核心源碼有一半是由驅動組成的,驅動在Linux完成其強大功能中扮演重要角色,而在開發自己的系統時,有時會發現無法再現成代碼中找到支援特定的硬體的驅動,這是就需要自己動手,才能“豐衣足食”了。^_^
自古以來,學習一門新程式設計語言的第一步就是寫一個列印“hello world”的程式,在本文中,我們將用同樣的方式學習編寫一個簡單的核心模組裝置驅動程式。
首先,建立一個hello.c檔案:
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
printk(KERN_ALERT "Hello, world\n");
}
static void hello_exit(void)
{
printk(KERN_ALERT "Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);
這個模組定義了兩個函數,一個在模組載入到核心時被調用(hello_init),一個在模組去除時被調用(hello_exit)。module_init和module_exit這幾行使用了特別的核心宏來指出這兩個函數的角色。另一個特別的宏(MODULE_LICENSE)是用來告知核心,該模組帶有一個自由的許可證,沒有這樣的說明,在模組載入時核心會報錯。
printk函數在Linux核心中定義並且對模組可用,它與標準C庫函數printf的行為相似。核心需要它自己的列印函數,因為沒有C庫的支援。字串KERN_ALERT是訊息的優先順序。在此模組中指定了一個高優先順序,因為使用預設優先順序的訊息可能不會直接顯示,這依賴於啟動並執行核心版本、klogd守護進程的版本以及配置。
為了編譯模組檔案,可以建立一個Makefile檔案,對本例來說,非常簡單,只需一行即可,命令如下:
obj-m := hello.o
obj-m指出將要編譯成的核心模組列表。*.o 格式檔案會自動地由相應的 *.c 檔案產生(不需要顯式地羅列所有原始碼檔案)
如果要把上述程式編譯為一個運行時載入和刪除的模組,則編譯命令如下所示。
make -C /usr/src/kernels/2.6.25-14.fc9.i686 M=$PWD modules
這個命令首先是改變目錄到用 -C 選項指定的位置(即核心原始碼目錄,這個參數要根據自己的情況而定)。這個 M= 選項使Makefile在構造modules目標前,返回到模組源碼目錄。然後,modules目標指向obj-m變數中設定的模組。這裡的編譯規則的意思是:在包含核心原始碼位置的地方進行make,然後再編譯
$PWD (當前)目錄下的modules。這裡允許我們使用所有定義在核心原始碼樹下的所有規則來編譯我們的核心模組。
編譯完畢之後,就會在原始碼目錄下產生hello.ko檔案,這就是核心驅動模組了。我們使用下面的命令來載入hello模組。
insmod hello.ko
下列命令完成相反的過程,即卸載hello模組。
rmmod hello
這時,你會發現終端裡什麼輸出也沒有,不用急,因為printk是核心輸出函數,要查看的話,還要執行下列指令。
dmesg | tail
這時,在終端裡就會列印出核心資訊了,如所示。
至此,一個最簡單的核心模組驅動程式就完成了。^_^