linux驱动模块的动态加载和静态加载
这里主要介绍动态加载:
一,编译,在指点内核树下编译,生成.o文件或.ko文件
二,将生成的.o或.ko文件拷到相应目录,一般是/lib/module/kernel下面
三,用insmod命令加载,用rmmod命令卸载
下面以举例的形式详细说明情况,需要注意的是,2.4内核与2.6内核不同,下面这个例子
真针对2.6内核,在2.4内核上我没试验成功,待研究:
1),源码:
#include <linux/module.h> /* 引入与模块相关的宏 */
#include <linux/init.h> /* 引入module_init() module_exit()函数 */
#include <linux/moduleparam.h> /* 引入module_param() */
MODULE_AUTHOR("Yang Qiu");
MODULE_LICENSE("GPL");
static int nbr = 10;
module_param(nbr, int, S_IRUGO);
static int __init yang_init(void)
{
int i;
for(i=0; i<nbr; i++)
{
printk(KERN_ALERT "Hello World. %d/n", i);
}
return 0;
}
static void __exit yang_exit(void)
{
printk(KERN_ALERT"I come from yang's module, I have been unlad./n");
}
module_init(yang_init);
module_exit(yang_exit);
2),编译,实现Makefile
obj-m := modules.o #要生成的模块名
modules-objs:= mymod.o #生成这个模块名所需要的目标文件
KDIR := /lib/modules/`uname -r`/build
PWD := $(shell pwd)
default:
make -C $(KDIR) M=$(PWD) modules
clean:
rm -rf *.o .* .cmd *.ko *.mod.c .tmp_versions
需要解释的是: obj-m是在内核定义的,指的是要产生的模块名
make -C $(KDIR) M=$(PWD) modules 很有意思的一句话,
-C指明要跳转到内核源码目录下读取那里的Makefile
M=$(PWD)表明然后返回当前目录,继续当前的Makefile.
需要注意的是,编译时文件可放在任何目录,只要KDIR := /lib/modules/`uname -r`/build 指向正确路径就OK了。
3),编译完后,在当前目录下会生成.ko文件,然后用insmod加载就行了。加载时,没有目录限制。
四,2.4内核的一直没有弄成功,提示错误说是内核不支持模块,还在研究待解决。
注:成功了
int init_module()
{
printk("Hello\n");
}
编译成功后,也用insmod命令成功地载入。但并没有任何输出..
A:
1.同时在另一个窗口,用命令tail -f /var/log/messages察看日志文件,会看到log
2.用dmesg命令。
它的输出是在内核log中,不是控制台
-----------------------------------------------------
printk()函数的总结
我们在使用printk()函数中使用日志级别为的是使编程人员在编程过程中自定义地进行信息的输出,更加容易地掌握系统当前的状况。
对程序的调试起到了很重要的作用。
(下文中的日志级别和控制台日志控制级别是一个意思)
printk(日志级别 "消息文本");这里的日志级别通俗的说指的是对文本信息的一种输出范围上的指定。
日志级别一共有8个级别,printk的日志级别定义如下(在linux26/includelinux/kernel.h中):
#defineKERN_EMERG"<0>"/*紧急事件消息,系统崩溃之前提示,表示系统不可用*/
#defineKERN_ALERT"<1>"/*报告消息,表示必须立即采取措施*/
#defineKERN_CRIT"<2>"/*临界条件,通常涉及严重的硬件或软件操作失败*/
#defineKERN_ERR"<3>"/*错误条件,驱动程序常用KERN_ERR来报告硬件的错误*/
#defineKERN_WARNING"<4>"/*警告条件,对可能出现问题的情况进行警告*/
#defineKERN_NOTICE"<5>"/*正常但又重要的条件,用于提醒。常用于与安全相关的消息*/
#defineKERN_INFO"<6>"/*提示信息,如驱动程序启动时,打印硬件信息*/
#defineKERN_DEBUG"<7>"/*调试级别的消息*/
没有指定日志级别的printk语句默认采用的级别是 DEFAULT_ MESSAGE_LOGLEVEL(这个默认级别一般为<4>,即与KERN_WARNING在一个级别上),其定义在linux26/kernel/printk.c中可以找到。
下面是一个比较简单的使用
printk(KERN_INFO "INFO\n"); //这里可以使用数字代替 KERN_INFO,即可以写成printk(<6> "INFO\n");
在这个格式的定义中,日志级别和信息文本之间不能够使用逗号隔开,因为系统在进行编译的时候,将日志级别转换成字符串于后面的文本信息进行连接。
在对系统输出进行控制时,主要是讨论控制台和伪终端的输情况,以及系统日志等。
下面是控制台日志级别的一些简要的介绍
控制台相应的日志级别定义如下:
#define MINIMUM_CONSOLE_LOGLEVEL 1 /*可以使用的最小日志级别*/
#define DEFAULT_CONSOLE_LOGLEVEL 7 /*比KERN_DEBUG 更重要的消息都被打印*/
int console_printk[4] = {
DEFAULT_CONSOLE_LOGLEVEL,/*控制台日志级别,优先级高于该值的消息将在控制台显示*/
/*默认消息日志级别,printk没定义优先级时,打印这个优先级以上的消息*/
DEFAULT_MESSAGE_LOGLEVEL,
/*最小控制台日志级别,控制台日志级别可被设置的最小值(最高优先级)*/
MINIMUM_CONSOLE_LOGLEVEL,
DEFAULT_CONSOLE_LOGLEVEL,/* 默认的控制台日志级别*/
};
在进行查看的时候,可以使用命令 cat /proc/sys/kernel/printk来查看这四个值
可以通过修改文件/proc/sys/kernel/printk中的第一个值来更改当前的控制台日志级别。
(声明:在下面的模块函数中控制台所使用的日志级别均为KERN_WARNING级别)当日志级别高于console_loglevel(控制台日志级别)时,消息才能在控制台显示出来。
假如我们写了一个如下的模块函数:
1 #include <linux/init.h>
2 #include <linux/module.h>
3 MODULE_LICENSE("Dual BSD/GPL");
4 static int book_init(void)
5 {
6 printk(KERN_EMERG "EMERG\n");
7 printk(KERN_ALERT "ALERT\n");
8 printk(KERN_CRIT " CRIT\n");
9 printk(KERN_ERR " ERR\n");
10 printk(KERN_WARNING ""WARNING\n");
11 printk(KERN_NOTICE "NOTICE\n");
12 printk(KERN_INFO "INFO\n");
13 printk(KERN_DEBUG "DEBUG\n");
14 return 0;
}
15static void book_exit(void)
16{
17 printk(KERN_ALERT "Book module exit\n");
}
18 module_init(book_init);
19 module_exit(book_exit);
在控制台(这里指的是虚拟终端 Ctrl+Alt+(F1~F6))加载模块以后,控制台给出的信息为
6~9行中要求输出的信息,我们在伪终端(如果对伪终端不是很清楚可以看相关的内容)上运行命令tail -n 10 /var/log/messages查看日志文件刚才得到的运行记录
可以发现messages中的值为KERN_WARNING级别之后所要求输出到信息值。而如果我们在文件syslog和kern-log中查看系统日志文件,一般情况下可以得到所有的输出信息
Jul 18 11:44:19 xiyoulinux-desktop kernel: [16100.637057] INFO
Jul 18 11:44:19 xiyoulinux-desktop kernel: [16100.637063] CRIT
Jul 18 11:44:19 xiyoulinux-desktop kernel: [16100.637066] WARNING
Jul 18 11:44:19 xiyoulinux-desktop kernel: [16100.637068] ERR
Jul 18 11:44:19 xiyoulinux-desktop kernel: [16100.637069] ALERT
Jul 18 11:44:19 xiyoulinux-desktop kernel: [16100.637070] EMERG
Jul 18 11:44:19 xiyoulinux-desktop kernel: [16100.637071] NOTICE
Jul 18 11:44:19 xiyoulinux-desktop kernel: [16100.637072] DEBUG
(不过在有些机器上运行得到的结果并不是这样的)
即一般情况下,syslog和kern.log两个文件中记录的内容从编程这个角度来看是基本一致的。
在目录/var/log/下有一下四个文件可以查看日志
syslog ,kern.log,messages ,DEBUG 。
syslog和kern.log一般情况下可以得到所有的系统输
出值,而messages得到的是比控制台日志级别低的输出值,DEBUG得到的仅仅是DEBUG级别的
输出值。
一般情况下,优先级高于控制台日志级别的消息将被打印到控制台。优先级低于控制台日志级别的消息将被打印到messages日志文件中,而在伪终端下不打印任何的信息。
我们在进行有关编程的时候,若使用到printk()这个函数,一般查看信息是在messages和虚拟终端下进行查看,而对于syslog和kern.log下是用来检验所有信息的输出情况。
注:模块的编译方式有两种:1,在内核里make module (选为M后)
2,单独给模块写makefile
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)