Linux內核編譯 一文中介紹了Linux 2.6內核的編譯與安裝工作,今天介紹一下Linux設備驅動開發的hello, world程序。
進行Linux設備驅動開發必須準備好Linux內核編譯環境,設備驅動程序依賴於這個環境。
下面是一個完整的hello, world驅動程序。
#include <linux/init.h>
#include <linux/module.h>
static int __init
hello_init(void)
{
printk("Hello, world!\n");
return 0;
}
module_init(hello_init);
static void __exit
hello_exit(void)
{
printk("Goodbye, world!\n");
}
module_exit(hello_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Valerie Henson <[email protected]>");
MODULE_DESCRIPTION("\"Hello, world!\" minimal module");
MODULE_VERSION("printk");
首先初始化函數和退出函數都聲明爲static類型,這是因爲這兩個函數不會被外部其它代碼調用。__init關鍵字告訴內核這是一個設備驅動程序的初始化函數,內核會並且只會調用一次該函數來進行驅動程序的初始化工作。同理,__exit關鍵字告訴內核這是一個設備驅動程序的退出函數,內核會並且只會調用一次該函數進行驅動程序的退出工作。
module_init(hello_init)用於設置設備驅動程序的初始化函數,module_exit(hello_exit)用於設置驅動程序的退出函數。
MODULE_LICENSE設置程序許可協議。如果不設置許可協議,內核會發出警告信息,設置內核某些功能不能被使用。
MODULE_AUTHOR設置程序作者。
MODULE_DESCRIPTION設置程序描述信息。
MODULE_VERSION設置程序版本。
程序的makefile如下:
obj-m := hello_printk.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) M=$(PWD) modules
obj-m指明需要編譯成的驅動程序,o文件由相應的c文件編譯得到。如果需要多個文件可以使用module-objs來列出多文件。
KDIR
是內核驅動模塊位置。
PWD是當前目錄。
default是makefile默認目標。
進入makefile所在目錄,運行make並將hello, world加載到內核。
yongmi@yongmi-hn:~/ldd/hello_printk$ make
make -C /lib/modules/2.6.32-5-686/build M=/home/yongmi/ldd/hello_printk modules
make[1]: Entering directory `/usr/src/linux-headers-2.6.32-5-686'
Building modules, stage 2.
MODPOST 1 modules
make[1]: Leaving directory `/usr/src/linux-headers-2.6.32-5-686'
yongmi@yongmi-hn:~/ldd/hello_printk$ su
Password:
root@yongmi-hn:/home/yongmi/ldd/hello_printk# insmod hello_printk.ko
root@yongmi-hn:/home/yongmi/ldd/hello_printk# dmesg | tail
[234781.145121] rtw_set_ps_mode(): Busy Traffic , Leave 802.11 power save..
[234781.145446] rtl8192c_set_FwPwrMode_cmd(): Mode = 0, SmartPS = 0
[234782.518827] survey done event(19)
[234783.704198] rtw_set_ps_mode(): Enter 802.11 power save mode...
[234783.704205] rtl8192c_set_FwPwrMode_cmd(): Mode = 1, SmartPS = 2
[234791.704197] rtw_set_ps_mode(): Busy Traffic , Leave 802.11 power save..
[234791.704316] rtl8192c_set_FwPwrMode_cmd(): Mode = 0, SmartPS = 0
[234793.704205] rtw_set_ps_mode(): Enter 802.11 power save mode...
[234793.704214] rtl8192c_set_FwPwrMode_cmd(): Mode = 1, SmartPS = 2
[234793.851115] Hello, world!
root@yongmi-hn:/home/yongmi/ldd/hello_printk#
可以看到驅動程序初始化函數被調用,在日誌文件中有hello, world字符串。
現在將hello, world驅動卸載下來:
root@yongmi-hn:/home/yongmi/ldd/hello_printk# rmmod hello_printk
root@yongmi-hn:/home/yongmi/ldd/hello_printk# dmesg | tail
[234975.704231] rtl8192c_set_FwPwrMode_cmd(): Mode = 1, SmartPS = 2
[234977.704225] rtw_set_ps_mode(): Busy Traffic , Leave 802.11 power save..
[234977.704340] rtl8192c_set_FwPwrMode_cmd(): Mode = 0, SmartPS = 0
[234979.704223] rtw_set_ps_mode(): Enter 802.11 power save mode...
[234979.704230] rtl8192c_set_FwPwrMode_cmd(): Mode = 1, SmartPS = 2
[234989.704231] rtw_set_ps_mode(): Busy Traffic , Leave 802.11 power save..
[234989.704331] rtl8192c_set_FwPwrMode_cmd(): Mode = 0, SmartPS = 0
[234991.704226] rtw_set_ps_mode(): Enter 802.11 power save mode...
[234991.704234] rtl8192c_set_FwPwrMode_cmd(): Mode = 1, SmartPS = 2
[234993.696774] Goodbye, world!
root@yongmi-hn:/home/yongmi/ldd/hello_printk#
內核調用了退出函數,並打印了Goodbye, world字符串。
本文簡要介紹了Linux設備驅動開發信息,程序中用到的代碼可以在這裏下載。
參考資料:
《Linux設備驅動開發》