购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

1.3 内核调试函数printk

本书中的模块代码用到了内核调试函数printk(),在用户空间里我们经常使用C语言函数printf()来向标准输出终端打印信息。printk()是内核使用的函数,因为内核没有链接到标准C函数库,其实printk()接口同printf()基本相似,printk()函数能够在终端一次最多显示大小为1024字节的字符串。printk()函数执行时首先设法获取控制台信号量,然后将要输出的字符存储到控制台的日志缓冲区,再调用控制台驱动程序来刷新缓冲区。若printk()无法获得控制台信号量,就只能把要输出的字符存储到日志缓冲区,并依赖拥有控制台信号量的进程来刷新这个缓冲区。printk()函数会将数据存储到日志缓冲区,但是为了安全考虑在这之前需要使用日志缓冲区锁,保证并发调用printk()的安全性。内核态系统信息输出函数printk()与用户态下的printf()函数在输出内容上也是有区别的,主要有两点:内核在切换模式时不保存处理器的浮点状态,因此printk()并不支持浮点数运算;printk()可以指定一个记录级别,内核根据这个级别来判断是否在终端上打印消息,而printf()函数则不需要。

printk()的语法格式为:


printk(记录级别
   “格式化输出信息”);

或者是采用编号形式:


printk(<记录级别编号>格式化输出信息”);

其中“记录级别”是include/linux/kern_levels.h中的简单宏定义,其在内核源代码中的形式如图1-2所示的第7~16行。它们扩展后是如“<number>”这样的字符串,加入printk()函数要打印的消息的前面。

图1-2 记录级别在内核源代码中的宏定义

内核用这个指定的记录等级和当前终端的记录等级console_loglevel进行比较,从而决定是不是向终端打印输出。表1-1给出了所有记录等级、字符串代号及说明。

表1-1 记录等级说明

内核将最重要的记录等级KERN_EMERG定为“<0>”,将无关紧要的记录等级KERN_DEBUG定为“<7>”。

例如:


printk(“没有等级信息,则采用默认级别!\n);
printk(KERN_INFO “内核提示信息\n);
printk(KERN_DEBUG “内核调试信息\n);

如果没有特别指定一个记录等级,函数会选用默认的DEFAULT_MESSAGE_LOGLEVEL,现在默认等级是KERN_WARNING。由于这个默认值将来存在变化的可能性,所以还是应该给消息指定一个记录等级。

本章后面的实例中考虑到使系统强制输出信息,所以我们使用了“<0>”级别,然后通过dmesg|tail或者是dmesg-c来查看系统输出信息。 ZUU7yYGT7apY2NhRp0RQpzrePRCknwC7s6TP3igkkMdHn7NW/cgOq7Q/ywWGq0pO

点击中间区域
呼出菜单
上一章
目录
下一章
×