查看系统调度流程:
以x86为例子:
在x86环境下其参数寄存器为:参数传递确实是按照rdi、rsi、rdx、rcx、r8、r9的顺序存放第一个参数到第六个参数
具体得出的方法见:https://blog.youkuaiyun.com/u010039418/article/details/85275211
要查看其参数调用流程,由系统的逻辑设计,参数的解析肯定是要在所有操作处理之前,所以我们应该要从系统的初始化入手:
我们先要找到入口, 通过
./arch/x86/kernel/vmlinux.lds.S
//我们可以查看到64位设备入口为phys_startup_64
OUTPUT_ARCH(i386:x86-64)
ENTRY(phys_startup_64)
//phys_startup_64目标地址为
. = __START_KERNEL;
phys_startup_64 = ABSOLUTE(startup_64 - LOAD_OFFSET);
//所以我们可以知道他的初始化地址为函数startup_64
//该函数的实现为:arch/x86/kernel/head_64.S中
//忽略掉其他项,我们找到参数相关处理项以及其下调用的函数
/*
* Perform pagetable fixups. Additionally, if SME is active, encrypt
* the kernel and retrieve the modifier (SME encryption mask if SME
* is active) to be added to the initial pgdir entry that will be
* programmed into CR3.
*/
leaq _text(%rip), %rdi
pushq %rsi
call __startup_64
popq %rsi
//所以我们可以判断参数被保存到了rsi中,然后后续__startup_64会去读取
//然后我们来到__startup_64函数实现中(arch/x86/kernel/head64.c)
unsigned long __head __startup_64(unsigned long physaddr,
struct boot_params *bp)
//从上我们发现__startup_64的第二个参数就是启动参数所以解析就应该在此
//查看boot_params结构体,发现这个是已经解析完的结构体对象了,我们关键是里面的ext_cmd_line_ptr处理者
arch/x86/kernel/head64.c x86_64_start_kernel会把参数的数据结构化并存储起来
x86_64_start_reservations(real_mode_data);//最后会到达了start_kernel()接口,这个就是关键了
在start_kernel()函数中,我们会进一步初始化各项内容,然后就到了重头戏parse_early_param() 这发生在
后续外设与系统初始化前解析好参数;
内核文档介绍:
./Documentation/admin-guide/kernel-parameters.rst
__setup(), early_param(), core_param() and module_param() macros
其中关于启动参数主要是__setup() 跟 early_param()
#define __setup_param(str, unique_id, fn, early) \
static const char __setup_str_##unique_id[] __initconst \
__aligned(1) = str; \
static struct obs_kernel_param __setup_##unique_id \
__used __section(".init.setup") \
__aligned(__alignof__(struct obs_kernel_param)) \
= { __setup_str_##unique_id, fn, early }
/*
* NOTE: __setup functions return values:
* @fn returns 1 (or non-zero) if the option argument is "handled"
* and returns 0 if the option argument is "not handled".
*/
#define __setup(str, fn) \
__setup_param(str, fn, fn, 0)
/*
* NOTE: @fn is as per module_param, not __setup!
* I.e., @fn returns 0 for no error or non-zero for error
* (possibly @fn returns a -errno value, but it does not matter).
* Emits warning if @fn returns non-zero.
*/
#define early_param(str, fn) \
__setup_param(str, fn, fn, 1)
参数解析项如下:
/* Check for early params. */
static int __init do_early_param(char *param, char *val,
const char *unused, void *arg)
{
const struct obs_kernel_param *p;
for (p = __setup_start; p < __setup_end; p++) {
if ((p->early && parameq(param, p->str)) ||
(strcmp(param, "console") == 0 &&
strcmp(p->str, "earlycon") == 0)
) {
if (p->setup_func(val) != 0)
pr_warn("Malformed early option '%s'\n", param);
}
}
/* We accept everything at this stage. */
return 0;
}
void __init parse_early_options(char *cmdline)
{
parse_args("early options", cmdline, NULL, 0, 0, 0, NULL,
do_early_param);
}
/* Arch code calls this early on, or if not, just before other parsing. */
void __init parse_early_param(void)
{
static int done __initdata;
static char tmp_cmdline[COMMAND_LINE_SIZE] __initdata;
if (done)
return;
/* All fall through to do_early_param. */
strscpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
parse_early_options(tmp_cmdline);
done = 1;
}
总结:
__setup定义了一个struct obs_kernel_param结构体变量,指明了参数名,非early,回调函数,并放到.init.setup段,它们是由parse_args进行解析并执行它的回调;
early_param与__setup类似,但是指明是early的,因此会由parse_early_param进行解析,并执行它的回调
直接grep 所有相关项并记录如下文件:
文件无法上传,后续知道操作后补充