您的位置:首页 > 其它

early_param、__setup、__tagtable分析

2015-06-02 23:31 381 查看
一、__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 = .;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: