问题
看kernel 代码的时候,总会重新烧内核,有时候乱改改挂了,但是发现串口启动log只打到了Starting kernel 就没了没有打出来,没法定位。
于是乎想研究一下内核启动时的串口log 是如何控制的?什么情况下会都打出来,以及什么时候没有打印
线索
经高人指点,说看一下内核启动参数bootargs。于是在内核启动后,dmesg看了下,果然发现了个疑点,启动参数里有个quiet 选项。
所以以此为线索看下内核是如何解析这个参数的。就从大名鼎鼎的start_kernel 开始找吧。
/* 首先init/main.c中可以找到这么一个定义,看起来就是我们要找的quiet 参数了 */
early_param("quiet", quiet_kernel);
__setup_param("quiet", quiet_kernel, quiet_kernel, 1)
static const char __setup_str_quiet_kernel[] __initconst __aligned(1) = "quiet";
static struct obs_kernel_param
__setup_quiet_kernel_id
__used __section(.init.setup)
__attribute__((aligned((sizeof(long)))))
= {__setup_str_quiet_kernel, quiet_kernel, 1}
/*简化一下,early_param("quiet", quiet_kernel) 大概等效于如下代码*/
static struct obs_kernel_param = {
.str = "quiet",
.setup_func = quiet_kernel,
.early = 1,
};
/*按照内核启动的流程*/
start_kernel()
parse_early_param();
parse_early_options(tmp_cmdline);
parse_args("early options", cmdline, NULL, 0, 0, 0, NULL, do_early_param);
...
do_early_param
for (p = __setup_start; p < __setup_end; p++) {
if ((p->early && parameq(param, p->str)) ||
(strcmp(param, "console") == 0 &&
strcmp(p->str, "earlycon") == 0)
) {
/* 此处的setup_func 就会调到quiet_kernel 函数了,后者会把console_loglevel = CONSOLE_LOGLEVEL_QUIET; */
if (p->setup_func(val) != 0)
pr_warn("Malformed early option '%s'\n", param);
}
}