我们的在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