我们的目的是要编译个hello.ko的文件,然后安装到内核中。
先来看下需要的代码,hello.c文件如下
#include <linux/module.h>
#include <linux/init.h>
static int hello_init(void)
{
printk(KERN_WARNING"Hello world!\n");
return 0;
}
static void hello_exit(void)
{
printk(KERN_INFO"Goodbye world!\n");
}
module_init(hello_init);
module_exit(hello_exit);
函数说明:
模块加载函数(必需)
安装模块时被系统自动调用的函数,通过module_init宏来指定。
模块卸载函数(必需)
卸载模块时被系统自动调用的函数,通过module_exit宏来指定。
1、Printk的打印级别如下:
级别 | 描述 |
KERN_EMERG |
紧急情况,系统可能会崩溃 |
KERN_ALERT |
必须立即响应 |
KERN_CRIT |
临界情况 |
KERN_ERR |
错误信息 |
KERN_WARNING |
警告信息 |
KERN_NOTICE |
普通的但可能需要注意的信息 |
KERN_INFO |
提示性信息 |
KERN_DEBUG |
调试信息 |
如果没有指定消息的级别,printk()会使用默认的DEFAULT_MESSAGE_LOGLEVEL(通常是KERN_WARNING)。
2、控制台的日志级别(console_loglevel)
当printk指定的消息级别小于指定的控制台日志级别时,消息的内容就会显示在该控制台上。控制台的日志级别定义在include/linux/kernel.h文件中,默认为DEFAULT_CONSOLE_LOGLEVEL(值等于7),也就是说默认情况下,比KERN_DEBUG级别高的printk()消息内容都可以在控制台上显示。
我们可以执行下面的命令使任何级别的printk()消息都被打印在终端上
$ echo 8 > /proc/sys/kernel/printk
3、printk()的变体
内核在include/linux/kernel.h文件中提供了两个printk()的变体pr_debug和pr_info,它们的定义为:
235 #define pr_debug(fmt,arg...) /
236 printk(KERN_DEBUG fmt,##arg)
244 #define pr_info(fmt,arg...) /
245 printk(KERN_INFO fmt,##arg)
4、 printk()不是万能的
printk()虽然很好用,但它并不是万能的,在系统启动时,终端还没有初始化之前,它并不能被使用,不过如果不是在调试系统的启动过程的话,这并不能算是个问题。
其实内核提供了一个printk()的变体early_printk(),专门用于在系统启动的初期在终端上打印消息,它与printk()的区别仅仅在于名字的不同以及它能够更早地工作。
Makefile文件如下ifneq ($(KERNELRELEASE),)
obj-m := hello.o
else
KERNELDIR ?= /home/grb/grb/arm/linux-2.6.38/
PWD := $(shell pwd)
all:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -f *.ko *.o *.mod.o *.mod.c *.symvers *~ *.order
endif
还有一种makefile的形式如下,可以做参考用
obj-m :=hello.o
KERNELDIR ?= /home/grb/grb/arm/linux-2.6.38/
PWD := $(shell pwd)
all:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -f *.ko *.o *.mod.o *.mod.c *.symvers *~ *.order
由makefile可以看出我都调用了/home/grb/grb/arm/linux-2.6.38/,这个路径是我已经交叉编译好了的友善之臂开发板的内核路径,所以这个路径可以根据自己实际情况做更改。
命令说明:
加载 insmod (insmod hello.ko)
卸载 rmmod (rmmod hello)
查看 lsmod
加载 modprobe (modprobe hello)
Modprobe 如同insmod,也是加载一个模块到内核,他的不同之处在于他会根据文件/lib/modules/<$version>/modules.dep来查看要加载的模块。看他是否还依赖于其他模块,如果是,modprobe会首先找到这些模块,把它们先加载到内核。
所有前期工作都准备好之后,便可以直接make了,如下这样就可以看到我们编译出来的hello.ko文件了。接下来就是安装测试了。将这个hello.ko文件拷贝到我们的开发板上,运行如下:
由结果可以看出,我们hello的内核模块是正常的了。