我正在阅读加载启动配置的内核代码。在 main.c 中执行以下代码。
err = parse_args("bootconfig", tmp_cmdline, NULL, 0, 0, 0, NULL,
bootconfig_params);
在第 428 行。我打开 parse_args,它内部调用 parse_one(都在 kernel/params.c 中),并且看起来由于为const struct kernel_param *params
NULL,它永远不会遍历任何参数parse_one
。
static void __init setup_boot_config(void)
我知道这里肯定有我遗漏的东西。据我所知,第 431 行和第 432 行之后的其余函数从未执行过。必须解析启动配置。
在init/main.c
https://elixir.bootlin.com/linux/v6.13.1/source/init/main.c中
static void __init setup_boot_config(void)
在kernel/params.c
https://elixir.bootlin.com/linux/v6.13.1/source/kernel/params.c中
parse_one(..)
parse_args(..)
setup_boot_config(void) >> parse_args(..) >> parse_one(..)
返回ENOENT
setup_boot_config(void)
检查
if (IS_ERR(err) || !(bootconfig_found || IS_ENABLED(CONFIG_BOOT_CONFIG_FORCE)))
并返回。xbc_init(..)
从未被调用。这里缺少了一些东西。
在 的入口处
parse_args()
,函数参数为:doing = "bootconfig"
args = tmp_cmdline
params = NULL
num_params = 0
min_level = 0
max_level = 0
arg = NULL
unknown = &(bootconfig_params)()
然后,在入口处
parse_one()
:param
=param
来自parse_args()
val
=val
来自parse_args()
doing = "bootconfig"
params = NULL
num_params = 0
min_level = 0
max_level = 0
arg = NULL
handle_unknown
=unknown
来自parse_args()
=&(bootconfig_params()
因为
num_params
是 0,所以跳过了第一个for
循环parse_one()
,然后我们到达这部分:以下是你错过的内容:
handle_unknown
是指向 的有效函数指针bootconfig_params()
,因此它不为 NULL。因此, 的内容if(handle_unknown)
将被执行,并且由于它包含无条件return
,它将决定 的结果parse_one()
。因此,在解析函数指针之后,返回的内容
parse_one()
将是任何bootconfig_params(param, val, doing, arg)
将返回的内容。那很简单:
因此,如果
param
是精确字符串"bootconfig"
,则bootconfig_found
设置为true
。但此函数始终返回 0... 这意味着parse_one()
也将返回 0... ,这将 设置ret
为parse_args()
0 而不是ENOENT
,因此switch(ret)
将转到continue
。因此,主
while (*args) ...
循环parse_args()
开始迭代到的下一个参数tmp_cmdline
。