驱动调试之printk原理

本文详细解析了U-Boot如何与Linux内核进行控制台通信的过程,包括内核对U-Boot传入的console参数处理、硬件控制台注册、printk函数工作原理及打印级别的修改方法。通过理解这些核心内容,读者可以深入掌握Linux内核的启动流程和控制台管理机制。

1、内核对uboot传进来的console=ttyAMA0处理

内核文件搜索"console="
在kernel/printk/printk.c找到
__setup(“console=”, console_setup);
__setup 为宏,将字符串console=,用console_setup函数处理
注意:此处记录了设备想用哪个控制台作为打印输出

2、硬件注册控制台

对于hi3519v101在下面路径注册,内核文件搜索"ttyAMA"
drivers/tty/serial/amba-pl011.c

static struct console amba_console = {
	.name		= "ttyAMA",
	.write		= pl011_console_write,
	.device		= uart_console_device,
	.setup		= pl011_console_setup,
	.flags		= CON_PRINTBUFFER,
	.index		= -1,
	.data		= &amba_reg,
};

#define AMBA_CONSOLE	(&amba_console)

3、printk

kernel/printk/printk.c

asmlinkage __visible int printk(const char *fmt, ...)
	vprintk_emit(0, -1, NULL, 0, fmt, args);
		vprintk_emit
			//这里会对printk的打印级别做处理
			//默认打印级别 4,把临时BUFFER里的数据稍作处理,再写入log_buf
			// 比如printk("abc")会得到"<4>abc", 再写入log_buf
			// 可以用dmesg命令把log_buf里的数据打印出来重现内核的输出信息
			default_message_loglevel
			// 如果可以级别够格打印
			if ((msg_log_level < console_loglevel
				__call_console_drivers
					con->write(con, &LOG_BUF(start), end - start);

4、修改打印级别console_loglevel

4.1系统启动之后修改
cat proc/sys/kernel/printk
7       4       1       7    //第一个7为默认控制台级别
echo "8 4 1 7" > proc/sys/kernel/printk 
cat proc/sys/kernel/printk   //修改为8,printk级别小于控制台级别才会打印
8       4       1       7
4.2修改默认的

如下文档有说明
Documentation/kernel-parameters.txt
loglevel= All Kernel Messages with a loglevel smaller than the
console loglevel will be printed to the console. It can
also be changed with klogd or other programs. The
loglevels are defined as follows:

		0 (KERN_EMERG)		system is unusable
		1 (KERN_ALERT)		action must be taken immediately
		2 (KERN_CRIT)		critical conditions
		3 (KERN_ERR)		error conditions
		4 (KERN_WARNING)	warning conditions
		5 (KERN_NOTICE)		normal but significant condition
		6 (KERN_INFO)		informational
		7 (KERN_DEBUG)		debug-level messages

loglevel在init/main.c有使用到
uboot传进来的loglevel值最终会赋给console_loglevel

static int __init loglevel(char *str)
{
	int newlevel;

	/*
	 * Only update loglevel value when a correct setting was passed,
	 * to prevent blind crashes (when loglevel being set to 0) that
	 * are quite hard to debug
	 */
	if (get_option(&str, &newlevel)) {
		console_loglevel = newlevel;
		return 0;
	}

	return -EINVAL;
}

early_param("loglevel", loglevel);

只要在uboot设置bootargs加上loglevel=某个值即可,如

set bootargs loglevel = 8 ...(其他内容不变)
save
reset

除了loglevel,还有其他的打印级别

static int __init debug_kernel(char *str)
{
	console_loglevel = CONSOLE_LOGLEVEL_DEBUG;
	return 0;
}

static int __init quiet_kernel(char *str)
{
	console_loglevel = CONSOLE_LOGLEVEL_QUIET;
	return 0;
}

early_param("debug", debug_kernel);
early_param("quiet", quiet_kernel);
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值