文章目录
内核调试方法有几种
printk()
printk的数据实际存放在数组log_buf,也在console打印。
dmesg
命令可以看到log_buf数组的打印数据,从这个文件/proc/kmsg
里读取,
/etc/fstab
文件系统表
/proc/mount
查看挂载情况
打印原理
内核会根据命令行参数(uboot传入)console=ttySAC0,内核用printk()打印,所以最终会调用到硬件的write函数,
关于console由add_preferred_console存放在console_cmdline里面的,
内核调用register_console获取console_cmdline的项,
kernel/printk.c,
1. uboot传入的使用console参数,保存在console_cmdline
__setup("console=", console_setup); // 宏函数生成结构体,内核中有很多这些结构体来处理参数,当内核处理参数时。
console_setup(char *str)
add_preferred_console(name, idx, options)// 根据参数记录这个控制台的名词
console_cmdline[MAX_CMDLINECONSOLES] // 数组存放控制台名称
2. 硬件驱动中 内核调用register_console选择console_cmdline数组的内容console
register_console(&s3c24xx_serial_console); // drivers/serial/s3c2410.c
s3c24xx_serial_console // 在同文件下定义如下,包含了name和write
static struct console s3c24xx_serial_console =
{
.name = S3C24XX_SERIAL_NAME, // #define S3C24XX_SERIAL_NAME "ttySAC"
.device = uart_console_device,
.flags = CON_PRINTBUFFER,
.index = -1,
.write = s3c24xx_serial_console_write,
.setup = s3c24xx_serial_console_setup
};
3. printk 最终调用到uboot传入参数对应硬件的write
asmlinkage int printk(const char *fmt, ...)
r = vprintk(fmt, args);
/* Emit the output into the temporary buffer */ 先把输出信息放入临时缓存区
printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args);
Copy the output into log_buf. /* 写入log_buf 这些打印信息在内核的字符数组里面(dmesg就是打印数组)*/ printk("<3>hello") // 打印级别,默认级别是<4>
release_console_sem();
call_console_drivers(_con_start, _log_end);
// 从log_buf获取数据 算出 打印级别
if ((msg_log_level < console_loglevel // 打印级别可以修改
_call_console_drivers(start_print, cur_index, msg_level);
__call_console_drivers(start & LOG_BUF_MASK, log_buf_len);
console->write(con, &LOG_BUF(start), end - start);
printk调试方法
#define DBG_PRINTK printk // 需要打印的时候
// #define DBG_PRINTK(x...) // 不需要打印时, 空的宏 ...表示参数可变
DBG_PRINTK("%s %s %s", __FILE__, __FUNCTION__, __LINE__ );
DBG_PRINTK("%s %s %s", __FILE__, __FUNCTION__, __LINE__ );
系统启动后,修改打印级别的阈值
查看cat /proc/sys/kernel/printk
,
修改 echo "8 4 1 7" > /proc/sys/kernel/printk
代码里边修改打印级别
直接改成0,所有的都不打印, kernel/printk.c的msg_log_level < console_loglevel --> msg_log_level < 0
uboot参数传递 添加设置 set bootargs loglevel=0 或者 set edbug 会打印所有信息
WDS笔记
驱动程序的调试
一. 打印: prink, 自制proc文件
UBOOT传入console=ttySAC0 console=tty1
-
内核处理UBOOT传入的参数
console_setup
add_preferred_console // 我想用名为"ttySAC0"的控制台,先记录下来 -
硬件驱动的入口函数里:
drivers/serial/s3c2410.c
register_console(&s3c24xx_serial_console); -
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 // 可以用dmesg命令把log_buf里的数据打印出来重现内核的输出信息 // 调用硬件的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);