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设备驱动开发》