第一个内核模块Hello.ko代码
1. 驱动代码hello.c的源码
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("Dual BSD/GPL");
static int hello_init(void)
{
printk(KERN_EMERG "Hello world enter \n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_EMERG "Hello world exit \n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_AUTHOR("Song Baohua");
MODULE_DESCRIPTION("A simple Hello world module");
MODULE_ALIAS("a simplest module");
2. 驱动编译Makefile的编写
ifeq ($(KERNELRELEASE),)
KDIR ?= /home/huzhu/msp700/03study_project/02msp700_linux/code
PWD := $(shell pwd)
modules:
$(MAKE) -C $(KDIR) M=$(PWD) modules
else
obj-m := hello.o
endif
KERNELRELEASE是在内核源码的顶层Makefile中定义的一个变量。
$(MAKE) -C $(KDIR) M=$(PWD) modules表示-C $(KDIR)进入linux内核所在的顶级目录,编译PWD路径下的代码,编译为modules内核模块.ko文件。
编译:# make生成hello.ko文件。
3. 驱动加载相关命令
insmod命令:insmod ./hello.ko加载驱动模块。
rmmod命令:rmmod hello卸载驱动模块。
lsmod命令:可以获得系统中加载了的所有模块以及模块间的依赖关系。lsmod命令实际上读取并分析/proc/modules文件,与cat /proc/modules效果一样。
内核中已加载模块的信息也存在于/sys/module目录下,加载hello.ko后,内核中将包含/sys/module/hello目录,在该目录下运行“tree -a”。
modprobe命令:modprobe命令比insmod命令强大,它加载模块时会同时加载该模块的依赖的模块。
modinfo命令:modinfo hello.ko模块名 命令可以获得模块信息。
4. 驱动调试总结
驱动代码中忘记添加module_init、module_exit函数,printk调试信息无打印,解决动作:1. 修改调试输出级别echo “7 4 1 7” > /proc/sys/kernel/printk,依旧无打印信息。2. 使用dmesg命令查看内核输出信息,依旧不能看到打印信息。3. 回想起代码make时有警告信息hello_init、hello_exit定义未使用,添加module_init消除警告,内核加载或卸载时可看到打印调试信息。
总结:编译时重视错误提示、也应该重视警告信息。