淘先锋技术网

首页 1 2 3 4 5 6 7

printk函数
       printk函数在linux内核中定义,功能和标准C库中的printf函数类似。因为内核需要自己的打印函数,又不能依赖于C库,模块在连接到内核之后就可以访问内核的公共符号。其中KERN_ALERT定义了这条消息的优先级。在<linux/kernel.h>中定义了8种记录级别,按照优先级递减的顺序分别是:

  1. KERN_EMERG:用于紧急消息,常常是那些崩溃前的消息<0>
  2. KERN_ALERT:需要立即行动的消息<1>
  3. KERN_CRIT:严重情况<2>
  4. KERN_ERR:错误情况<3>
  5. KERN_WARNING:有问题的警告<4>
  6. KERN_NOTICE:正常情况,但是仍然值的注意<5>
  7. KERN_INFO:信息型消息<6>
  8. 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
       但是我们最终测试发现,如果不包含这个kernel.h这个头文件依然是可以访问到这个printk这个函数的。有可能是当模块直接使用了内核符号表中的东西。