内核启动参数调用流程

文章详细阐述了在x86环境下,参数如何按照特定寄存器顺序传递,并从系统初始化的入口开始,追踪参数解析的过程,涉及函数如phys_startup_64、__startup_64、__head__startup_64等。在start_kernel()函数中,参数通过__setup()和early_param()宏进行处理,parse_early_param()用于在系统初始化前解析参数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

查看系统调度流程:

以x86为例子:

在x86环境下其参数寄存器为:参数传递确实是按照rdi、rsi、rdx、rcx、r8、r9的顺序存放第一个参数到第六个参数

具体得出的方法见:https://blog.youkuaiyun.com/u010039418/article/details/85275211

要查看其参数调用流程,由系统的逻辑设计,参数的解析肯定是要在所有操作处理之前,所以我们应该要从系统的初始化入手:

  1. 我们先要找到入口, 通过

./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 所有相关项并记录如下文件:

文件无法上传,后续知道操作后补充

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值