printk函数
printk函数在linux内核中定义,功能和标准C库中的printf函数类似。因为内核需要自己的打印函数,又不能依赖于C库,模块在连接到内核之后就可以访问内核的公共符号。其中KERN_ALERT定义了这条消息的优先级。在<linux/kernel.h>中定义了8种记录级别,按照优先级递减的顺序分别是:
- KERN_EMERG:用于紧急消息,常常是那些崩溃前的消息<0>
- KERN_ALERT:需要立即行动的消息<1>
- KERN_CRIT:严重情况<2>
- KERN_ERR:错误情况<3>
- KERN_WARNING:有问题的警告<4>
- KERN_NOTICE:正常情况,但是仍然值的注意<5>
- KERN_INFO:信息型消息<6>
- KERN_DEBUG:用作调试消息<7>
如果没有指定优先级的话,那么printk默认使用DEFAULT_MESSAGE_LOGLEVEL优先级,他是在kernel/printk.c中定义的整数。
#define DEFAULT_MESSAGE_LOGLEVEL 4 //KERN_WARNING
如果运行以上代码,你并没有发现控制台有打印输出,那么这些内容可能输出到某个系统日志中了,可以使用dmesg | tail -n 10来打印系统日志的最后10行。
printk函数是位于kernel/printk.h中定义的,以下为该函数的源码
/**
* printk - print a kernel message
* @fmt: format string
*
* This is printk(). It can be called from any context. We want it to work.
*
* We try to grab the console_lock. If we succeed, it's easy - we log the output and
* call the console drivers. If we fail to get the semaphore we place the output
* into the log buffer and return. The current holder of the console_sem will
* notice the new output in console_unlock(); and will send it to the
* consoles before releasing the lock.
*
* One effect of this deferred printing is that code which calls printk() and
* then changes console_loglevel may break. This is because console_loglevel
* is inspected when the actual printing occurs.
*
* See also:
* printf(3)
*
* See the vsnprintf() documentation for format string extensions over C99.
*/
asmlinkage int printk(const char *fmt, ...)
{
va_list args;
int r;
#ifdef CONFIG_KGDB_KDB
if (unlikely(kdb_trap_printk)) {
va_start(args, fmt);
r = vkdb_printf(fmt, args);
va_end(args);
return r;
}
#endif
va_start(args, fmt);
r = vprintk(fmt, args);
va_end(args);
return r;
}
我们再看linux/kernel.h,发现kernel.h已经将printk.h包含了。
但是我们最终测试发现,如果不包含这个kernel.h这个头文件依然是可以访问到这个printk这个函数的。有可能是当模块直接使用了内核符号表中的东西。