printk函数是我们调试linux内核必备的打印接口,
printk定义在/kernel/路径下
声明在/linux/kernel.h中,如果在某个文件中使用printk时编译通不过,通常都是未包含这个头文件(当然还有语法错误,呵呵~)
/**
* 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_sem. 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 release_console_sem() and will send it to the
* consoles before releasing the semaphore.
*
* 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.
*/
asmlinkageint printk(const char *fmt, ...)
{
va_list args;
int r;
va_start(args, fmt);
r = vprintk(fmt, args);
va_end(args);
return r;
}
/*
1.asmlinkage: 是GCC的c语言扩展语法,函数定义前加宏asmlinkage ,表示这些函数通过堆栈而不是通过寄存器传递参数。
2.printk是支持可变参数的,我们都知道一般情况下形参存储在动态数据区的栈区,但是const修饰的会存储在静态数据区,
不管形参在什么地方存储,有一点是不变的就是形参的存储是连续的;
其实不只是printk,只要支持可变参数,它们都有一个共同点:就是第一参数必须给定,根据第一个参数的地址,
就可以找后续的参数,以及参数的个数,以为它们是有逗号分隔的(这个就是实现可变参数的原理)
*/
asmlinkage int vprintk(const char *fmt, va_list args)
{
int printed_len = 0;
int current_log_level = default_message_loglevel;
unsigned long flags;
int this_cpu;
char *p;
boot_delay_msec();
printk_delay();
preempt_disable(); //禁止抢占
/* This stops the holder of console_sem just where we want him */
raw_local_irq_save(flags); //保存本地为处理的中断,这点我不是特别确认,只是根据字面意思理解的
this_cpu = smp_processor_id();//获得CPU id
/*
* Ouch, printk recursed into itself!
*/
if (unlikely(printk_cpu == this_cpu)) {
/*
* If a crash is occurring during printk() on this CPU,
* then try to get the crash message out but make sure
* we can't deadlock. Otherwise just return to avoid the
* recursion and return - but flag the recursion so that
* it can be printed at the next appropriate moment:
*/
if (!oops_in_progress) {
recursion_bug = 1;
goto out_restore_irqs;
}
zap_locks();</