您的位置:首页 > 其它

各种initcall的执行顺序: module_init subsys_initcall ....

2015-03-09 17:57 696 查看
先从module_init 开刀:一层一层的把宏展开

#define module_init(x) __initcall(x);

#define __initcall(fn) device_initcall(fn)

#define device_initcall(fn) __define_initcall(fn, 6)

#define __define_initcall(fn, id) \

static initcall_t __initcall_##fn##id __used \

__attribute__((__section__(".initcall" #id ".init"))) = fn

到这里就已经不再是宏了。这个属于gcc的attribute语法了。最后的结果就是把传给module_init的函数名组装成以__initcall为前缀的、以6为后缀的函数名,并把这个函数定义到代 码段.initcall6.init里面

在code中搜索相关的字符串,得到了如下的结果:

define INIT_CALLS_LEVEL(level) \

VMLINUX_SYMBOL(__initcall##level##_start) = .; \

*(.initcall##level##.init) \

*(.initcall##level##s.init) \

#define INIT_CALLS \

VMLINUX_SYMBOL(__initcall_start) = .; \

*(.initcallearly.init) \

INIT_CALLS_LEVEL(0) \

INIT_CALLS_LEVEL(1) \

INIT_CALLS_LEVEL(2) \

INIT_CALLS_LEVEL(3) \

INIT_CALLS_LEVEL(4) \

INIT_CALLS_LEVEL(5) \

INIT_CALLS_LEVEL(rootfs) \

INIT_CALLS_LEVEL(6) \

INIT_CALLS_LEVEL(7) \

VMLINUX_SYMBOL(__initcall_end) = .;

#define INIT_DATA_SECTION(initsetup_align) \

.init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { \

INIT_DATA \

INIT_SETUP(initsetup_align) \

INIT_CALLS \

CON_INITCALL \

SECURITY_INITCALL \

INIT_RAM_FS \

}

看来最终这些代码段都跑到 INIT_CALLS 中去了。INIT_CALLS 又被包到 INIT_DATA_SECTION 里面。

中间那些汇编的语法就暂时停留在“知其然”的层次上吧。

static initcall_t *initcall_levels[] __initdata = {

__initcall0_start,

__initcall1_start,

__initcall2_start,

__initcall3_start,

__initcall4_start,

__initcall5_start,

__initcall6_start,

__initcall7_start,

__initcall_end,

};

最后这些函数会被调用:

static void __init do_initcall_level(int level)

{

extern const struct kernel_param __start___param[], __stop___param[];

initcall_t *fn;

strcpy(static_command_line, saved_command_line);

parse_args(initcall_level_names[level],

static_command_line, __start___param,

__stop___param - __start___param,

level, level,

&repair_env_string);

for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)

do_one_initcall(*fn);

}

static void __init do_initcalls(void)

{

int level;

for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++)

do_initcall_level(level);

}

所以其调用顺序就是由这个宏里面的数字决定的:

#define device_initcall(fn) __define_initcall(fn, 6)

#define subsys_initcall(fn) __define_initcall(fn, 4)

所以其先后顺序就清楚了。subsys_initcall 的优先级比 module_init 的优先级要高。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐