驱动调试之printk的原理
UBOOT传入 console=ttySAC0 console=tty1
1. 内核处理UBOOT传入的参数
__setup("console=", console_setup); //当内核处理参数时,会调用console_setup来处理 //Linux-4.9.88\kernel\printk\printk.c
console_setup
add_preferred_console // 我想用名为"ttySAC0"的控制台,先记录下来
2. 硬件驱动的入口函数里:
drivers/serial/s3c2410.c
register_console(&s3c24xx_serial_console); //与 console_setup 内添加的匹配,s3c24xx_serial_console 是结构体,含有.name,.write成员
3. printk
vprintk
/* Emit the output into the temporary buffer */
// 先把输出信息放入临时BUFFER
vscnprintf
// Copy the output into log_buf.
// 把临时BUFFER里的数据稍作处理,再写入log_buf
// 比如printk("abc")会得到"<4>abc", 再写入log_buf 添加打印级别,如没有,则默认添加为<4>
// 可以用dmesg命令把log_buf里的数据打印出来重现内核的输出信息 //可以通过 cat /proc/kmsg,dmesg 查看
// 调用硬件的write函数输出
release_console_sem();
call_console_drivers(_con_start, _log_end);
// 从log_buf得到数据,算出打印级别
_call_console_drivers(start_print, cur_index, msg_level);
// 如果可以级别够格打印
if ((msg_log_level < console_loglevel //打印级别判断,是否打印
__call_console_drivers
con->write(con, &LOG_BUF(start), end - start); //即调用s3c24xx_serial_console 的.write函数
驱动调试之printk的使用
(1)内核运行时,可定义是否打印调试信息
printk(KERN_DEBUG"%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
可通过 cat /proc/sys/kernel/printk 查看记录级别,console_loglevel、default_message_loglevel、minimum_console_loglevel和default_console_loglevel。
echo "1 4 1 7" > /proc/sys/kernel/printk //大于1级别的 所有的printk信息都不会被打印
echo "8 4 1 7" > /proc/sys/kernel/printk //可打印KERN_DEBUG(级别为7) 级别的信息
(2)uboot传入参数,定义是否打印信息
static int __init loglevel(char* str)
{
get_option(&str, &console_loglevel);
return 1;
}
__setup("loglevel=", loglevel) //可在uboot命令行传入loglevel=X,修改 console_loglevel 级别
static int __init debug_kernel(char *str)
{
if (*str)
return 0;
console_loglevel = 10;
return 1;
}
static int __init quiet_kernel(char *str)
{
if (*str)
return 0;
console_loglevel = 4;
return 1;
}
__setup("debug", debug_kernel);
__setup("quiet", quiet_kernel);
参考:韦东山Linux教程
标签:__,kernel,console,prink,loglevel,setup,驱动,printk,调试 From: https://www.cnblogs.com/charlie12345/p/17682280.html