美文网首页
Linux内核__setup()宏介绍

Linux内核__setup()宏介绍

作者: 小田BSP | 来源:发表于2021-08-04 22:52 被阅读0次

Linux内核中可使用宏__setup()处理内核的启动参数cmdline的解析。

一、宏解析

文件:include/linux/init.h

定义:

/*
 * Only for really core code.  See moduleparam.h for the normal way.
 *
 * Force the alignment so the compiler doesn't space elements of the
 * obs_kernel_param "array" too far apart in .init.setup.
 */
#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)               \                 
        __attribute__((aligned((sizeof(long)))))        \
        = { __setup_str_##unique_id, fn, early }

#define __setup(str, fn)                        \
    __setup_param(str, fn, fn, 0)

通过宏展开可以看出:宏__setup()主要是定义了一个obs_kernel_param类型的结构体变量__setup_fn

## 结构体obs_kernel_param定义
struct obs_kernel_param {
    const char *str;
    int (*setup_func)(char *); ## 内核启动时,调用该函数解析__setup()中str传递的值
    int early;
};

二、应用实例

RockPI 4A单板Debian系统Linux 4.4内核为例,介绍init参数的解析方法。

1、cmdline参数

Debian系统中,通过extlinux.conf文件传递启动参数,其中init=/sbin/init,如下:

root@linaro-alip:/boot/extlinux# cat extlinux.conf
...

label kernel-debug
    ...
    append earlyprintk console=ttyFIQ0,1500000n8 init=/sbin/init root=PARTUUID=b921b045-1d rw rootwait rootfstype=ext4 no_console_suspend initcall_debug

2、__setup()宏定义

Linux内核中,解析init参数的__setup()实现如下:

## init/main.c
static int __init init_setup(char *str)
{
    unsigned int i;

    execute_command = str;     ##str 即: /sbin/init
    /*
     * In case LILO is going to boot us with default command line,
     * it prepends "auto" before the whole cmdline which makes
     * the shell think it should execute a script with such name.
     * So we ignore all arguments entered _before_ init=... [MJ]
     */
    for (i = 1; i < MAX_INIT_ARGS; i++)
        argv_init[i] = NULL;
    return 1;
}
__setup("init=", init_setup);

3、__setup()宏展开

展开宏__setup("init=", init_setup),即:

    static const char __setup_str_init_setup[] __initconst      \
        __aligned(1) = "init=";                     \

    static struct obs_kernel_param __setup_init_setup       \
        __used __section(.init.setup)               \                
        __attribute__((aligned((sizeof(long)))))        \
        = { __setup_str_init_setup, init_setup, 0 }                    ## __setup_str_init_setup 在上面定义

内核编译完成后,在内核符号表System.map文件中,可以看到__setup_init_setup

ffffff800920dd48 t __setup_init_setup

4、函数调用流程

内核启动后,init_setup()函数的调用流程如下:

## init/main.c
start_kernel()->
    parse_args()->
        parse_one()->
            unknown_bootoption()->
                obsolete_checksetup()->
                    setup_func()-> ## 调用obs_kernel_param定义的setup_func(),即init_setup()
                        init_setup()

相关文章

网友评论

      本文标题:Linux内核__setup()宏介绍

      本文链接:https://www.haomeiwen.com/subject/joypvltx.html