do_initcalls()将按顺序从由__initcall_start开始,到__initcall_end结束的section中以函数指针的形式取出这些编译到内核的驱动模块中初始化函数起始地址,来依次完成相应的初始化。而这些初始化函数由__define_initcall(level,fn)指示编译器在编译的时候,将这些初始化函数的起始地址值按照一定的顺序放在这个section中。
由于内核某些部分的初始化需要依赖于其他某些部分的初始化的完成,因此这个顺序排列常常非常重要。先看看调用源码:
static void __init do_initcalls(void)
{
int level;
for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++)
do_initcall_level(level);//依次调用不同等级的初始化函数
}
extern initcall_t __initcall_start[];
extern initcall_t __initcall0_start[];
extern initcall_t __initcall1_start[];
extern initcall_t __initcall2_start[];
extern initcall_t __initcall3_start[];
extern initcall_t __initcall4_start[];
extern initcall_t __initcall5_start[];
extern initcall_t __initcall6_start[];
extern initcall_t __initcall7_start[];
extern initcall_t __initcall_end[];
static initcall_t *initcall_levels[] __initdata = {
__initcall0_start,
__initcall1_start,
__initcall2_start,
__initcall3_start,
__initcall4_start,
__initcall5_start,
__initcall6_start,
__initcall7_start,
__initcall_end,
};
/* Keep these in sync with initcalls in include/linux/init.h */
static char *initcall_level_names[] _

本文详细分析了Linux 3.6版本中do_initcalls函数的工作原理,该函数负责按顺序执行内核初始化阶段的驱动模块。通过__define_initcall宏定义,函数地址被放入特定的section,根据level决定初始化顺序。内核启动时,do_initcalls会遍历这些section调用函数,完成初始化任务。
最低0.47元/天 解锁文章
8081

被折叠的 条评论
为什么被折叠?



