Linux/Android启动之Machine-Init函数
前言:
前面写过两篇Linux/Android的启动过程分析,这篇接着前两篇的知识点进行分析。
Linux/Android的启动过程包括了很多内容,其中有些需要了解,有些则需要在系统移植的时候进行修改。本篇文章主要来讲述Machine-Init函数在系统启动过程中如何被调用的以及在何时被调用。
Linux中的Machine-Init在功能和调用位置上类似于Win CE/ Windows Mobile中的OAL初始化函数OEMInit。
哈哈。如果有不正确或者不完善的地方,欢迎前来拍砖留言或者发邮件到guopeixin@126.com进行讨论,先行谢过。
一. 基础知识
1. Linux启动过程中驱动模块初始化的位置
Linux OS的启动过程中将会去创建线程kernel_init,该线程负责Driver初始化等一系列工作。线程kernel_init将会依次调用do_basic_setup()àdo_initcalls()àdo_one_initcall(),并在do_initcalls()中完成对各个驱动模块Init函数的调用。
这部分代码如下:
函数do_basic_setup()如下:
/* * Ok, the machine is now initialized. None of the devices * have been touched yet, but the CPU subsystem is up and * running, and memory and process management works. * * Now we can finally start doing some real work.. */ static void __init do_basic_setup(void) { rcu_init_sched(); /* needed by module_init stage. */ init_workqueues(); usermodehelper_init(); driver_init(); init_irq_proc(); do_initcalls(); } |
函数do_initcalls():
extern initcall_t __initcall_start[], __initcall_end[], __early_initcall_end[]; static void __init do_initcalls(void) { initcall_t *call;
for (call = __early_initcall_end; call < __initcall_end; call++) do_one_initcall(*call);
/* Make sure there is no pending stuff from the initcall sequence */ flush_scheduled_work(); } |
函数do_one_initcall(initcall_t fn)如下:
int initcall_debug; core_param(initcall_debug, initcall_debug, bool, 0644);
int do_one_initcall(initcall_t fn) { int count = preempt_count(); ktime_t calltime, delta, rettime; char msgbuf[64]; struct boot_trace_call call; struct boot_trace_ret ret;
if (initcall_debug) { call.caller = task_pid_nr(current); printk("calling %pF @ %i/n", f |