MACHINE_START 调用 系统初始化 分析

我们的在arch 目录下可以看到很多的板级支持包  核心的就是  MACHINE_START 开头的

MACHINE_START(SUN7I, "sun7i")
.atag_offset = 0x100,
.timer          = &sw_sys_timer,
.map_io         = sun7i_map_io,
.init_early     = NULL,
.init_irq = gic_init_irq,
.init_machine   = sw_core_init,
.reserve        = sw_core_reserve,
.restart = sun4i_restart,
#ifdef CONFIG_MULTI_IRQ_HANDLER
.handle_irq = gic_handle_irq,
#endif
#ifdef CONFIG_ZONE_DMA
.dma_zone_size = SZ_256M,
#endif
MACHINE_END

#define MACHINE_START(_type,_name) \
static const struct machine_desc __mach_desc_##_type \
 __used \
 __attribute__((__section__(".arch.info.init"))) = { \
.nr = MACH_TYPE_##_type, \
.name = _name,


#define MACHINE_END \
};

MACHINE_START(SUN7I, "sun7i")  展开之后就是

static const struct machine_desc __mach_desc_SUN7I 

__used

__attribute__((__section__(".arch.info.init"))) = {

.nr =MACH_TYPE_SUN7I,

        .name =  "sun7i"

}

现在再看 就不是那么难以理解了。

我们知道 这个结构体实现了 一个板子底层的底层支持。但是它是何时被调用呢??它的这些函数又是何时被运行呢?

首先系统启动从/init/main.c 的start_kernel 函数-->>setup_arch()函数调用了MACHINE_START的部分函数 ,但是却没有init_machine   函数 我找了半天还是没有找到,最后没有办法只好搜索源码 最后终于找到

static int __init customize_machine(void)
{
/* customizes platform devices, or adds new ones */
if (machine_desc->init_machine)
machine_desc->init_machine();
return 0;
}
arch_initcall(customize_machine);

这个函数,可以看到这个函数调用了init_machine()函数。但是谁调用了它呢?何时调用的呢?

这次搜索函数名字 是没有用处的,根本找不到。

#define arch_initcall(fn) __define_initcall("3",fn,3)   

这个宏是唯一的线索。

我们跟踪并分析。。

#define __define_initcall(level,fn,id) \
static initcall_t __initcall_##fn##id __used \
__attribute__((__section__(".initcall" level ".init"))) = fn

关键点应该就在这里了。

我分析的时候参考了这篇文章,希望帮到大家。

http://blog.chinaunix.net/uid-26772535-id-3262471.html


下面看vmlinux.lds.h

#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) = .;

看到这里大家应该都笑了吧!!!哥们终于找到你了

找到是找到了,可是何时被调用呢?又是如何调用的呢?

各位请接着看main.c  start_kernel()函数  -->>rest_init()-->>kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);


kernel_init()-->>do_basic_setup()-->>do_initcalls()

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,
};


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);
}


do_one_initcall() 这个函数调用了所有的函数,包括init_machine   


猜你喜欢

转载自blog.csdn.net/haozhenghui10/article/details/40211959