early_param、__setup、__tagtable分析

来源:互联网 发布:淘宝女装店铺头像logo 编辑:程序博客网 时间:2024/05/11 12:56

一、__tagtable分析,对于arm平台,解析uboot向内核传递的参数

//对应文件 arch\arm\include\asm\setup.h

struct tagtable {
__u32 tag;
int (*parse)(const struct tag *);
};
#define __tag               __used __attribute__((__section__(".taglist.init")))
#define __tagtable(tag, fn) static struct tagtable __tagtable_##fn __tag = { tag, fn }

tagtable(ATAG_MEM, parse_tag_mem32)

展开后,该结构体变量会放在.taglist.init段中
static struct tagtable __tagtable_parse_tag_mem32 __used __attribute__((__section__(".taglist.init"))) = 

ATAG_MEM, 
parse_tag_mem32 
}

//调用过程

start_kernel->setup_arch->parse_tags->parse_tag

static int __init parse_tag(const struct tag *tag)
{
extern struct tagtable __tagtable_begin, __tagtable_end;
struct tagtable *t;

//.taglist.init段中的结构体中对应的函数都会被执行

for (t = &__tagtable_begin; t < &__tagtable_end; t++)
if (tag->hdr.tag == t->tag) {
t->parse(tag);
break;
}
return t < &__tagtable_end;
}

arch/arm/kernel/vmlinux.lds.S

__tagtable_begin = .;
*(.taglist.init)
__tagtable_end = .;


二、early_param、__setup,对于x86平台,解析grub.cfg等向内核传递的参数

//include/linux/init.h

struct obs_kernel_param {
const char *str;
int (*setup_func)(char *);
int early;
};

#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(str,fn)其展开为

static struct obs_kernel_param __setup_fn__used __section(.init.setup)__attribute__((aligned((sizeof(long)))))= 

str 
fn, 
0
}


#define early_param(str, fn) __setup_param(str, fn, fn, 1)

//其展开为

static struct obs_kernel_param __setup_fn__used __section(.init.setup)__attribute__((aligned((sizeof(long)))))= 


str,
fn, 
1
}

early_param、__setup都是放在.init.setup段中的结构体变量.

early_param/__setup调用过程,二次解析

第一次解析,解析early_param结构体函数

start_kernel->parse_early_param->parse_early_options->parse_args("early options", cmdline, NULL, 0, do_early_param);

static int __init do_early_param(char *param, char *val)
{
struct obs_kernel_param *p;
for (p = __setup_start; p < __setup_end; p++) {/*在.init.setup段中结构体中依次执行相应的函数*/
if ((p->early && strcmp(param, p->str) == 0) ||  /*p->early=1即解析的是early_param结构体函数*/ 
   (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;
}

第二次解析,解析__setup结构体函数

start_kernel->parse_args("Booting kernel", static_command_line, __start___param,__stop___param - __start___param,&unknown_bootoption);  


arch/arm/kernel/vmlinux.lds.S

__setup_start = .;
*(.init.setup)
__setup_end = .;


0 0