__setup

r囧r小猫 2023-06-05 08:24 69阅读 0赞

原文网址:__setup_IT利刃出鞘的博客-CSDN博客___setup

目录

作用

示例

定义

调用流程


作用

根据传入的字符串参数,与bootloader传递的参数(bootargs)进行匹配,从而调用传入的函数

示例

static int __init cmdline_test_setup(char *s)
{
printk(“%s\n”, s);
return 1;
}
__setup(“test=”, cmdline_test_setup);
若bootloader的bootargs中包含“test=hello”,则会打印出“hello”

定义

include/linux/init.h:228:#define __setup(str, fn)

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

#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 }

static int __init cmdline_test_setup(char *s)
{
printk(“%s\n”, s);
return 1;
}
__setup(“test=”, cmdline_test_setup);

__setup_param(“test=”, cmdline_test_setup, cmdline_test_setup, 0)
static const char __setup_str_cmdline_test_setup[] __initconst __aligned(1) = “test=”;
static struct obs_kernel_param __setup_unique_cmdline_test_setup __used __section(.init.setup) __attribute__((aligned((sizeof(long))))) = {
__setup_str_cmdline_test_setup,
cmdline_test_setup,
0
}
简单来讲就是定义了一个 obs_kernel_param 结构题变量,它的名字叫做 __setup_test_setup,里面有三个成员,
分别是 char数组__setup_str_test_setup=”test=” 、函数test_setup 、 一个叫做early的变量,此处的值为0。
重点是,这个结构体变量被存放进了.init.setup 段。

调用流程

vmlinux.lds.h:
#define INIT_SETUP(initsetup_align) \
. = ALIGN(initsetup_align); \
VMLINUX_SYMBOL(__setup_start) = .; \
*(.init.setup) \
VMLINUX_SYMBOL(__setup_end) = .;

main.c kernel/init
start_kernel()
parse_early_param() //main.c kernel/init
parse_early_options(tmp_cmdline);
parse_args(“early options”, cmdline, NULL, 0, 0, 0, NULL, do_early_param); //kernel/params.c
//最终调用do_early_param //main.c kernel/init
parse_args(“Booting kernel”, static_command_line, __start___param, __stop___param - __start___param, &unknown_bootoption);
//最终调用unknown_bootoption //main.c kernel/init
char *param, *val;
… …
while (*args) {
int ret;
int irq_was_disabled;

args = next_arg(args, &param, &val);
irq_was_disabled = irqs_disabled();
ret = parse_one(param, val, params, num, unknown);
… …
}
解析bootloader传给kernel的参数,在while循环里将参数一个个的取出,丢给 parse_one 函数

do_early_param和unknown_bootoption区别
static int __init do_early_param(char *param, char *val)
{
const struct obs_kernel_param *p;

for (p = __setup_start; p < __setup_end; p++) {
if ((p->early && strcmp(param, p->str) == 0) ||
(strcmp(param, “console”) == 0 &&
strcmp(p->str, “earlycon”) == 0)
) {
if (p->setup_func(val) != 0)
printk(KERN_WARNING
“Malformed early option ‘%s’\n”, param);
}
}
/* We accept everything at this stage. */
return 0;
}

首先定义了 struct obs_kernel_param *p, 还记得我们在分解 __setup 宏的时候提到过 名字叫做 __setup_video_setup 的 obs_kernel_param 变量,这个的指针p就是它。
然后从 __setup_start 开始遍历到 __setup_end,根据上面 vmlinux.lds.h 的代码知道,就是遍历整个 .init.setup 段。
看代码 “ (p->early && strcmp(param, p->str) == 0) ” 这边就体现了 early 的作用了,原来early 的值假如不为0,则会被更早得解析处理到。
随后,将param(从bootloader传过来的)和 p->str(__setup传进来的)进行匹配,若匹配成功,则调用 p->setup_func 方法,这个方法也是我们 __setup 自己定义传进来的。
unknown_bootoption 函数的功能类似,但它不会处理 p->early = 0 的数据。

发表评论

表情:
评论列表 (有 0 条评论,69人围观)

还没有评论,来说两句吧...

相关阅读

    相关 setup语法糖

    > 提示: vue3.2 版本开始才能使用语法糖! 1、如何使用setup语法糖 > 只需在 script 标签上写上 setup 代码如下(示例): <t

    相关 __setup

    > 原文网址:[\_\_setup\_IT利刃出鞘的博客-CSDN博客\_\_\_setup][setup_IT_-CSDN_setup] > > 目录 > > 作用

    相关 Linux setup命令

    Linux setup命令设置公用程序,是一个启动图形设置系统的命令。 setup 命令:用来配置X,打印设置,时区设置,系统服务,网络配置,配置,防火墙配置,验证配置,...