1. 程式人生 > >Linux啟動流程-bootloader至kernel的過程--android系統啟動流程

Linux啟動流程-bootloader至kernel的過程--android系統啟動流程

1 Bootloader

對於一般的ARM處理器,CPU上電或復位執行第一條指令所在地址,即第一段程式Bootloader的開始地址,Bootloader一般存於Nor-flash(XIP),支援晶片內執行。

Bootloader的功能可總結為:1)初始化CPU時鐘,記憶體,串列埠等。2)設定Linux啟動引數。3)載入Linux核心映象。Android原始碼位於根目錄下的/bootable資料夾。

系統正常啟動,執行Bootloader,初始化晶片,根據設定的啟動引數cmdline,載入Linux核心映象,將控制權交給核心。

系統在Bootloader模式下(非正常啟動模式),可使用fastboot, mmcboot等工具燒寫核心和檔案系統,順便提一下,Android手機分割槽一般分為核心區boot.img,系統區system.img,使用者資料區userdata.img,資料恢復區recovery.img等。

2 Linux核心映象

核心映象被載入到記憶體,首先進行自解壓,zImage, bzImage或uImage的頭部都內嵌有解壓縮程式,最終將核心解壓到記憶體的指定位置,開始執行核心。

3 啟動核心

原始碼位於/kernel/init/main.c,線索可歸納為:啟動核心start_kernel() => 初始化Linux各大模組 + rest_init() => 開啟核心執行緒kthreadd和kernel_init() => 初始化裝置驅動程式do_basic_setup() + init_post() => 開啟第一個使用者程序init。

3.1 start_kernel()

原始碼位於/kernel/init/main.c的start_kernel()函式,完成初始化Linux系統的程序管理,記憶體管理,檔案系統等工作,可以說個個都是重量級的工作。

這裡有必要解釋下核心選項,因為Linux各個子系統的初始化都建立在核心選項的解析之後。

parse_early_param();
parse_args("Booting kernel", static_command_line, __start___param,
  __stop___param - __start___param, &unknown_bootoption);

1) 核心選項的註冊

通過__early_parm(str, fn)或__setup(str, fn)巨集來註冊。兩者都呼叫__setup_param巨集實現,它將註冊的核心選項str所關聯的函式fn存放到.init.setup節

  


2) 核心選項的解析

兩次註冊對應兩次解析,即parse_early_param()和parse_param(),解析時,會在__setup_start和__setup_end之間查詢核心選項,當識別有核心選項時,即會呼叫相應的處理函式。核心解析完後,各個子系統的初始化就可通過kernel_init()=>do_basic_setup()=>do_initcalls()來完成。

3.2 reset_init()

開啟核心執行緒kthreadd和kernel_init,kthreadd用來執行kthread_create_list全域性連結串列中的kthread,然後建立idle執行緒來佔用掉cpu空閒的時間片

核心執行緒又叫守護程序,關於核心執行緒和Linux普通程序的區別,歸納為以下三點:

  • 核心執行緒執行的是核心中的函式,而普通程序只有通過系統呼叫才能執行核心中的函式。
  • 核心執行緒只執行在核心態,而普通程序既可以執行在使用者態,也可以執行在核心態。
  • 因為核心執行緒指只執行在核心態,因此,它只能使用大於PAGE_OFFSET(3G)的地址空間。另一方面,不管在使用者態還是核心態,普通程序可以使用4GB的地址空間。

3.3 kernel_init()

此時與體系相關的部分已經初始化完成,do_basic_setup()開始初始化裝置,完成外設及驅動程式(直接編譯進核心的模組)的載入和初始化。

3.4 init_post()

開啟init使用者程序,所謂Android的啟動流程從這裡才剛剛開始。

1. init程序

2. zygote程序

2.1 AndroidRuntime

2.2 ZygoteInit

3. system_server程序

3.1 init1階段

3.2 init2階段

接著Linux啟動部分 http://blog.csdn.net/qianjin0703/article/details/6881107

1. init程序


系統在核心空間初始化程序,記憶體,檔案系統,驅動模組之後,呼叫init_post()函式,開啟第一個使用者程序init,進入使用者空間。

/kernel/init/main.c (僅擷取部分重要程式碼)

[plain] view plaincopyprint?
  1. static noinline int init_post(void)  
  2. {  
  3.     run_init_process("/sbin/init");  
  4.     run_init_process("/etc/init");  
  5.     run_init_process("/bin/init");  
  6.     run_init_process("/bin/sh");  
  7. }  
static noinline int init_post(void)
{

	run_init_process("/sbin/init");
	run_init_process("/etc/init");
	run_init_process("/bin/init");
	run_init_process("/bin/sh");
}

終端下檢視1號程序,


可見,init是系統守護程序和zygote的父程序。

/system/core/init/init.c 

[plain] view plaincopyprint?
  1. int main(int argc, char **argv)  
  2. {  
  3.     mkdir("/dev", 0755);  
  4.     mkdir("/proc", 0755);  
  5.     mkdir("/sys", 0755);  
  6.     mount("devpts", "/dev/pts", "devpts", 0, NULL);  
  7.     mount("proc", "/proc", "proc", 0, NULL);  
  8.     mount("sysfs", "/sys", "sysfs", 0, NULL);  
  9.     open_devnull_stdio();  
  10.     klog_init();  
  11.     property_init();  
  12.     get_hardware_name(hardware, &revision);  
  13.     process_kernel_cmdline();  
  14.     init_parse_config_file("/init.rc");  
  15.     action_for_each_trigger("early-init", action_add_queue_tail);  
  16.     queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done");  
  17.     queue_builtin_action(keychord_init_action, "keychord_init");  
  18.     queue_builtin_action(console_init_action, "console_init");  
  19.     action_for_each_trigger("init", action_add_queue_tail);  
  20.     for(;;) {  
  21.         execute_one_command();  
  22.         restart_processes();  
  23.         nr = poll(ufds, fd_count, timeout);  
  24.         for (i = 0; i < fd_count; i++) {  
  25.             if (ufds[i].revents == POLLIN) {  
  26.                 if (ufds[i].fd == get_property_set_fd())  
  27.                     handle_property_set_fd();  
  28.                 else if (ufds[i].fd == get_keychord_fd())  
  29.                     handle_keychord();  
  30.                 else if (ufds[i].fd == get_signal_fd())  
  31.                     handle_signal();  
  32.             }  
  33.         }  
  34.     }  
  35.     return 0;  
  36. }  
int main(int argc, char **argv)
{

    mkdir("/dev", 0755);
    mkdir("/proc", 0755);
    mkdir("/sys", 0755);

    mount("devpts", "/dev/pts", "devpts", 0, NULL);
    mount("proc", "/proc", "proc", 0, NULL);
    mount("sysfs", "/sys", "sysfs", 0, NULL);

    open_devnull_stdio();
    klog_init();
    property_init();

    get_hardware_name(hardware, &revision);
    process_kernel_cmdline();

    init_parse_config_file("/init.rc");
    action_for_each_trigger("early-init", action_add_queue_tail);

    queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done");
    queue_builtin_action(keychord_init_action, "keychord_init");
    queue_builtin_action(console_init_action, "console_init");
    action_for_each_trigger("init", action_add_queue_tail);

    for(;;) {

        execute_one_command();
        restart_processes();

        nr = poll(ufds, fd_count, timeout);

        for (i = 0; i < fd_count; i++) {
            if (ufds[i].revents == POLLIN) {
                if (ufds[i].fd == get_property_set_fd())
                    handle_property_set_fd();
                else if (ufds[i].fd == get_keychord_fd())
                    handle_keychord();
                else if (ufds[i].fd == get_signal_fd())
                    handle_signal();
            }
        }
    }

    return 0;
}

init程序歸納如下

  • 解析init.rc和init.*.rc
  • 掛載檔案系統,建立資料夾和檔案,設定許可權,為一些檔案寫入初值
  • 初始化property屬性
  • 啟動系統守護程序如adbd, vold, rild等
  • 啟動zygote程序



2. zygote程序

zygote既是Android系統建立java世界的盤古,又是繁殖system_server和所有應用程式的女媧。

終端下檢視zygote程序,


2.1 AndroidRuntime

/frameworks/base/cmds/app_process/app_main.cpp

[cpp] view plaincopyprint?
  1. int main(int argc, constcharconst argv[])  
  2. {  
  3.     AppRuntime runtime;  
  4. if (zygote) {  
  5.         runtime.start("com.android.internal.os.ZygoteInit",  
  6.                 startSystemServer ? "start-system-server" : "");  
  7. }  
int main(int argc, const char* const argv[])
{

    AppRuntime runtime;

    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit",
                startSystemServer ? "start-system-server" : "");
}

AppRuntime是從AndroidRuntime類派生的,最後由runtime.start()進入Java世界。

/frameworks/base/core/jni/AndroidRuntime.cpp

[cpp] view plaincopyprint?
  1. void AndroidRuntime::start(constchar* className, constchar* options)  
  2. {  
  3. /* start the virtual machine */
  4.     JNIEnv* env;  
  5. if (startVm(&mJavaVM, &env) != 0) {  
  6. return;  
  7.     }  
  8.     onVmCreated(env);  
  9. /* 
  10.      * Register android functions. 
  11.      */
  12. if (startReg(env) < 0) {  
  13.         ALOGE("Unable to register all android natives\n");  
  14. return;  
  15.     }  
  16. /* 
  17.      * Start VM.  This thread becomes the main thread of the VM, and will 
  18.      * not return until the VM exits. 
  19.      */
  20. char* slashClassName = toSlashClassName(className);  
  21.     jclass startClass = env->FindClass(slashClassName);  
  22.     jmethodID startMeth = env->GetStaticMethodID(startClass, "main",  
  23. "([Ljava/lang/String;)V");  
  24.     env->CallStaticVoidMethod(startClass, startMeth, strArray);  
  25. }  
void AndroidRuntime::start(const char* className, const char* options)
{

    /* start the virtual machine */
    JNIEnv* env;
    if (startVm(&mJavaVM, &env) != 0) {
        return;
    }
    onVmCreated(env);

    /*
     * Register android functions.
     */
    if (startReg(env) < 0) {
        ALOGE("Unable to register all android natives\n");
        return;
    }

    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
    char* slashClassName = toSlashClassName(className);
    jclass startClass = env->FindClass(slashClassName);

    jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
            "([Ljava/lang/String;)V");

    env->CallStaticVoidMethod(startClass, startMeth, strArray);

}

-> 建立虛擬機器

注意這裡會設定虛擬機器的heapsize,預設16M,一般32M,不能太小,否則在操作大尺寸圖片時無法分配所需記憶體。

-> 註冊jni函式

這裡註冊了本地方法,這些方法最終被編譯進動態連結庫libandroid_runtime.so,供上層Java呼叫。

[cpp] view plaincopyprint?
  1. staticconst RegJNIRec gRegJNI[] = {  
  2.     REG_JNI(register_android_debug_JNITest),  
  3.     REG_JNI(register_com_android_internal_os_RuntimeInit),  
  4.     REG_JNI(register_android_os_SystemClock),  
  5.     REG_JNI(register_android_util_Log),  
  6.     REG_JNI(register_android_os_Process),  
  7.     REG_JNI(register_android_os_SystemProperties),  
  8.     REG_JNI(register_android_os_Binder),  
  9.     REG_JNI(register_android_view_Display),  
  10.     REG_JNI(register_android_graphics_Bitmap),  
  11.     REG_JNI(register_android_graphics_Camera),  
  12.     REG_JNI(register_android_database_SQLiteDatabase),  
  13.     REG_JNI(register_android_os_Power),  
  14.     REG_JNI(register_android_os_StatFs),  
  15.     REG_JNI(register_android_net_NetworkUtils),  
  16.     REG_JNI(register_android_nfc_NdefMessage),  
  17.     REG_JNI(register_com_android_internal_os_ZygoteInit),  
  18.     REG_JNI(register_android_hardware_Camera),  
  19.     REG_JNI(register_android_hardware_SensorManager),  
  20.     REG_JNI(register_android_hardware_UsbDevice),  
  21.     REG_JNI(register_android_media_AudioRecord),  
  22.     REG_JNI(register_android_media_AudioSystem),  
  23.     REG_JNI(register_android_media_AudioTrack),  
  24.     REG_JNI(register_android_opengl_classes),  
  25.     REG_JNI(register_android_bluetooth_BluetoothSocket),  
  26.     REG_JNI(register_android_server_BluetoothService),  
  27.     REG_JNI(register_android_app_ActivityThread),  
  28.     REG_JNI(register_android_app_NativeActivity),  
  29.     REG_JNI(register_android_view_InputChannel),  
  30.     REG_JNI(register_android_view_InputQueue),  
  31.     REG_JNI(register_android_view_KeyEvent),  
  32.     REG_JNI(register_android_view_MotionEvent),  
  33.     REG_JNI(register_android_view_PointerIcon),  
  34. };  
static const RegJNIRec gRegJNI[] = {
    REG_JNI(register_android_debug_JNITest),
    REG_JNI(register_com_android_internal_os_RuntimeInit),
    REG_JNI(register_android_os_SystemClock),
    REG_JNI(register_android_util_Log),
    REG_JNI(register_android_os_Process),
    REG_JNI(register_android_os_SystemProperties),
    REG_JNI(register_android_os_Binder),
    REG_JNI(register_android_view_Display),
    REG_JNI(register_android_graphics_Bitmap),
    REG_JNI(register_android_graphics_Camera),
    REG_JNI(register_android_database_SQLiteDatabase),
    REG_JNI(register_android_os_Power),
    REG_JNI(register_android_os_StatFs),
    REG_JNI(register_android_net_NetworkUtils),
    REG_JNI(register_android_nfc_NdefMessage),
    REG_JNI(register_com_android_internal_os_ZygoteInit),
    REG_JNI(register_android_hardware_Camera),
    REG_JNI(register_android_hardware_SensorManager),
    REG_JNI(register_android_hardware_UsbDevice),
    REG_JNI(register_android_media_AudioRecord),
    REG_JNI(register_android_media_AudioSystem),
    REG_JNI(register_android_media_AudioTrack),
    REG_JNI(register_android_opengl_classes),
    REG_JNI(register_android_bluetooth_BluetoothSocket),
    REG_JNI(register_android_server_BluetoothService),

    REG_JNI(register_android_app_ActivityThread),
    REG_JNI(register_android_app_NativeActivity),
    REG_JNI(register_android_view_InputChannel),
    REG_JNI(register_android_view_InputQueue),
    REG_JNI(register_android_view_KeyEvent),
    REG_JNI(register_android_view_MotionEvent),
    REG_JNI(register_android_view_PointerIcon),

};

2.2 ZygoteInit

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

[java] view plaincopyprint?
  1. publicstaticvoid main(String argv[]) {  
  2. try {  
  3.         SamplingProfilerIntegration.start();  
  4.         registerZygoteSocket();  
  5.         preload();  
  6.         SamplingProfilerIntegration.writeZygoteSnapshot();  
  7. if (argv[1].equals("start-system-server")) {  
  8.             startSystemServer();  
  9.         }   
  10.             runSelectLoopMode();  
  11.         closeServerSocket();  
  12.     }   
  13. }  
    public static void main(String argv[]) {
        try {
            SamplingProfilerIntegration.start();

            registerZygoteSocket();

            preload();

            SamplingProfilerIntegration.writeZygoteSnapshot();

            if (argv[1].equals("start-system-server")) {
                startSystemServer();
            } 

                runSelectLoopMode();

            closeServerSocket();
        } 
    }

-> 建立服務端Socket

zygote及系統中其他程式的通訊沒有使用Binder,而是採用了基於AF_UNIX型別的Socket.

-> 預載入類和資源

預載入的類可以在 /frameworks/base/preloaded-classes 檢視。預載入的資源生成framewrok-res.apk,主要是一些圖示,刷機達人經常修改它。

-> 啟動system_server程序

zygote程序fork出system_server子程序,把任務繁重的系統服務全部託管出去,自己負責迴圈監聽所有應用程式的請求。

-> 等待應用程式的請求

zygote通過runSelectLoopMode()處理應用程式客戶端的請求,由ZygoteConnection的runOnce()孵化出新的應用程式。

綜上所述,zygote程序歸納如下

  • 建立虛擬機器
  • 註冊jni函式
  • 預載入類和資源
  • 啟動system_server程序
  • 監聽應用程式請求

3. system_server程序

/frameworks/base/services/java/com/android/SystemServer.java

[java] view plaincopyprint?
  1. publicstaticvoid main(String[] args) {  
  2.     System.loadLibrary("android_servers");  
  3.     init1(args);  
  4. }  
    public static void main(String[] args) {

        System.loadLibrary("android_servers");
        init1(args);
    }

3.1 init1階段
載入libandriod_server.so庫,實現init1

/frameworks/base/cmds/system_server/library/system_init.cpp

[cpp] view plaincopyprint?
  1. extern"C" status_t system_init()  
  2. {  
  3.     sp<GrimReaper> grim = new GrimReaper();  
  4.     sm->asBinder()->linkToDeath(grim, grim.get(), 0);  
  5. char propBuf[PROPERTY_VALUE_MAX];  
  6.     property_get("system_init.startsurfaceflinger", propBuf, "1");  
  7. if (strcmp(propBuf, "1") == 0) {  
  8. // Start the SurfaceFlinger
  9.         SurfaceFlinger::instantiate();  
  10.     }  
  11.     property_get("system_init.startsensorservice", propBuf, "1");  
  12. if (strcmp(propBuf, "1") == 0) {  
  13. // Start the sensor service
  14.         SensorService::instantiate();  
  15.     }  
  16.     AndroidRuntime* runtime = AndroidRuntime::getRuntime();  
  17.     jclass clazz = env->FindClass("com/android/server/SystemServer");  
  18.     jmethodID methodId = env->GetStaticMethodID(clazz, "init2""()V");  
  19.     env->CallStaticVoidMethod(clazz, methodId);  
  20. return NO_ERROR;  
  21. }  
extern "C" status_t system_init()
{

    sp<GrimReaper> grim = new GrimReaper();
    sm->asBinder()->linkToDeath(grim, grim.get(), 0);

    char propBuf[PROPERTY_VALUE_MAX];
    property_get("system_init.startsurfaceflinger", propBuf, "1");
    if (strcmp(propBuf, "1") == 0) {
        // Start the SurfaceFlinger
        SurfaceFlinger::instantiate();
    }

    property_get("system_init.startsensorservice", propBuf, "1");
    if (strcmp(propBuf, "1") == 0) {
        // Start the sensor service
        SensorService::instantiate();
    }

    AndroidRuntime* runtime = AndroidRuntime::getRuntime();

    jclass clazz = env->FindClass("com/android/server/SystemServer");
    jmethodID methodId = env->GetStaticMethodID(clazz, "init2", "()V");
    env->CallStaticVoidMethod(clazz, methodId);

    return NO_ERROR;
}



3.2 init2階段

init2回到Java層,啟動一個ServerThread執行緒,啟動系統的各項服務。