1.用printk打印调试
最常用的调试技术是监视, 在应用程序编程当中是通过在合适的地方调用printf 来实现. 在你调试内核代码时, 你可以通过 printk 来达到这个目的.
使用 printk 函数, 简单地假设它如同 printf 一样使用. 现在介绍一些不同的地方.
一个不同是 printk 允许你根据消息的严重程度对其分类, 通过附加不同的记录级别或者优先级在消息上. 你常常用一个宏定义来指示记录级别. 例如, KERN_INFO, 我们之前曾在一些打印语句的前面看到过, 是消息记录级别的一种可能值. 记录宏定义扩展成一个字串, 在编译时与消息文本连接在一起;这就是为什么下面的在优先级和格式串之间没有逗号的原因. 这里有 2 个printk 命令的例子, 一个调试消息, 一个紧急消息:
printk(KERN_DEBUG “Here I am: %s:%i\n”, __FILE__, __LINE__);
printk(KERN_CRIT “I’m trashed; giving up on %p\n”, ptr);
有 8 种可能的记录字串, 在头文件 里定义; 我们按照严重性递减的顺序列出它们:
KERN_EMERG
用于紧急消息, 常常是那些崩溃前的消息.
KERN_ALERT
需要立刻动作的情形.
KERN_CRIT
严重情况, 常常与严重的硬件或者软件失效有关.
KERN_ERR
用来报告错误情况; 设备驱动常常使用 KERN_ERR 来报告硬件故障.
KERN_WARNING
有问题的情况的警告, 这些情况自己不会引起系统的严重问题.
KERN_NOTICE
正常情况, 但是仍然值得注意. 在这个级别一些安全相关的情况会报告.
KERN_INFO
信息型消息. 在这个级别, 很多驱动在启动时打印它们发现的硬件的信息.
KERN_DEBUG
用作调试消息.
每个字串( 在宏定义扩展里 )代表一个在角括号中的整数. 整数的范围从 0到 7, 越小的数表示越大的优先级.
一条没有指定优先级的 printk 语句缺省是 DEFAULT_MESSAGE_LOGLEVEL, 在kernel/printk.c 里指定作为一个整数. 在 2.6.10 内核中, DEFAULT_MESSAGE_LOGLEVEL 是 KERN_WARNING, 但是在过去一直是改变的.
基于记录级别, 内核可能打印消息到当前控制台, 可能是一个文本模式终端,串口, 或者是一台并口打印机. 如果优先级小于整型值 console_loglevel,消息被递交给控制台, 一次一行。
2.速率限制
如果你不小心, 你会发现自己用 printk 产生了上千条消息, 压倒了控制台并且, 可能地, 使系统日志文件溢出. 当使用一个慢速控制台设备(例如, 一个串口), 过量的消息速率也能拖慢系统或者只是使它不反应了. 非常难于着手于系统出错的地方, 当控制台不停地输出数据. 因此, 你应当非常注意你打印什么, 特别在驱动的产品版本以及特别在初始化完成后. 通常, 产品代码在正常操作时不应当打印任何东西; 打印的输出应当是指示需要注意的异常情况.
另一方面, 你可能想发出一个日志消息, 如果你驱动的设备停止工作. 但是你应当小心不要做过了头. 一个面对失败永远继续的傻瓜进程能产生每秒上千次的尝试; 如果你的驱动每次都打印“my device is broken”, 它可能产生大量的输出, 如果控制台设备慢就有可能霸占 CPU — 没有中断用来驱动控制台, 就算是一个串口或者一个行打印机.
在很多情况下, 最好的做法是设置一个标志说, “我已经抱怨过这个了“,并不打印任何后来的消息只要这个标志设置着. 然而, 有几个理由偶尔发出一个“设备还是坏的“的提示. 内核已经提供了一个函数帮助这个情况:
int printk_ratelimit(void);
这个函数应当在你认为打印一个可能会常常重复的消息之前调用. 如果这个函数返回非零值, 继续打印你的消息, 否则跳过它. 这样, 典型的调用如这样:
if (printk_ratelimit())
printk(KERN_NOTICE “The printer is still on fire\n”);
printk_ratelimit 通过跟踪多少消息发向控制台而工作. 当输出级别超过一个限度, printk_ratelimit 开始返回 0 并使消息被扔掉.
printk_ratelimit 的行为可以通过修改/proc/sys/kern/printk_ratelimit( 在重新使能消息前等待的秒数 ) 和/proc/sys/kernel/printk_ratelimit_burst(限速前可接收的消息数)来定制.
阅读(582) | 评论(0) | 转发(0) |