Android bootコードフロー1

39712 ワード

以前のこの編では、androidの起動プロセス全体が全体的に示されていたが、androidの起動がコードレベルでどのように呼び出されたのかを明らかにするために、ソースコードの観点から分析され、他のすべてのコードはandroid 4.0 source treeに基づいている.
all story begin with the init process startupストーリーinitプロセス開始から
Init運転、コード:system/core/init、入口:system/core/init.c main関数:
 1 int main(int argc, char **argv){

 2     

 3      ...

 4     //        

 5     mkdir("/dev", 0755);

 6     mkdir("/proc", 0755);

 7     mkdir("/sys", 0755);

 8 

 9     mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");

10     mkdir("/dev/pts", 0755);

11     mkdir("/dev/socket", 0755);

12     mount("devpts", "/dev/pts", "devpts", 0, NULL);

13     mount("proc", "/proc", "proc", 0, NULL);

14     mount("sysfs", "/sys", "sysfs", 0, NULL);

15 

16     ...
17 // /init.rc /init.$hardware.rc , $hardware /proc/cpuinfo , goldfish 18 INFO("reading config file
"); 19 init_parse_config_file("/init.rc"); 20 21 /* pull the kernel commandline and ramdisk properties file in */ 22 import_kernel_cmdline(0, import_kernel_nv); 23 /* don't expose the raw commandline to nonpriv processes */ 24 chmod("/proc/cmdline", 0440); 25 get_hardware_name(hardware, &revision); 26 snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware); 27 init_parse_config_file(tmp); 28 29 ... 30 }

解析init.rcファイル、主に/system/core/init/init_parser.cで完了し、initを切り取る.rcの一部の内容は以下の通りです:(具体的なinit.rcファイル仕様、参照:/system/core/init/readme.txt)
on early-init

    start ueventd



# create mountpoints

    mkdir /mnt 0775 root system



# setup the global environment

    export PATH /sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin



# Create cgroup mount points for process groups

    mkdir /dev/cpuctl

    mount cgroup none /dev/cpuctl cpu

    chown system system /dev/cpuctl

    chown system system /dev/cpuctl/tasks

    chmod 0777 /dev/cpuctl/tasks

    write /dev/cpuctl/cpu.shares 1024



service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server

    class main

    socket zygote stream 666

    onrestart write /sys/android_power/request_state wake

    onrestart write /sys/power/state on

    onrestart restart media

    onrestart restart netd

 init.rcはandroid init language仕様を使用しており、4つの文、Actions、Commands、Services、Optionsをサポートしています.
  • Action定義方式:
  • on <trigger>                        #  on   ,        ,    3   :
    <command> #1. , : on early-init; 
      <command>                #2.name=value , :on property:vold.decrypt=trigger_reset_main;
    <command> #3. , :device-added-<path>,device-removed-<path>,service-exited-<name>
    <command> # , :start...,mkdir,...
  • Commandは、export、hostname、mkdir、mountなど、システムがサポートする一連のコマンドです.その一部はlinuxコマンドで、androidが追加したものもあります.class_start:サービス開始、class_stop:サービスを閉じるなど. 
  • Service定義:
  • service <name> <pathname> [ <argument> ]*
    
       <option>
    
       <option>
    
       ...
    
    
    
    # :   android        zygote 
    
    service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    
        class main
    
        socket zygote stream 666
    
        onrestart write /sys/android_power/request_state wake
    
        onrestart write /sys/power/state on
    
        onrestart restart media
    
        onrestart restart netd
  • Optionは、サービスのオプションです.たとえば、
  • setenv <name> <value>                                       
    
    user <username>                                           
    
    oneshot                                         
    
    class <classname>                               
    socket <name> <type> <perm> [ <user> [ <group> ] ]       <name> socket, socket
    onrestart <command>                         <command>

    はい、そうです.rcとinit.$hardware.rc 2ファイルはandroid init language仕様に従って解析が完了すると、実行するコマンドはすべて大きなaction_に配置されます.Listでは、initファイルの下を解析します.
      //    early-init    ,   action_queue  
    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(property_init_action, "property_init"); queue_builtin_action(keychord_init_action, "keychord_init"); queue_builtin_action(console_init_action, "console_init"); queue_builtin_action(set_init_properties_action, "set_init_properties"); /* execute all the boot actions to get us started */ action_for_each_trigger("init", action_add_queue_tail); /* skip mounting filesystems in charger mode */ if (strcmp(bootmode, "charger") != 0) { action_for_each_trigger("early-fs", action_add_queue_tail); action_for_each_trigger("fs", action_add_queue_tail); action_for_each_trigger("post-fs", action_add_queue_tail); action_for_each_trigger("post-fs-data", action_add_queue_tail); } queue_builtin_action(property_service_init_action, "property_service_init"); queue_builtin_action(signal_init_action, "signal_init"); queue_builtin_action(check_startup_action, "check_startup"); if (!strcmp(bootmode, "charger")) { action_for_each_trigger("charger", action_add_queue_tail); } else { action_for_each_trigger("early-boot", action_add_queue_tail); action_for_each_trigger("boot", action_add_queue_tail); } /* run all property triggers based on current state of the properties */ queue_builtin_action(queue_property_triggers_action, "queue_propety_triggers");      ...
      
      // action_queue for(;;) { int nr, i, timeout = -1; execute_one_command(); restart_processes(); ... }

    Action_からlistで作成トリガを見つけ、トリガが実行するコマンドをaction_に追加します.Queueでは、最後にaction_を順番に実行します.queueのコマンドは初期化を完了し、いくつかの環境変数を設定したりフォルダを作成したりする以外は初期化を完了します.
    もっと多いのはサービスの起動に関心を持って、initファイルの中のサービスは2種類あって、1種類はclass coreで、1種類はclass mainで、init.rcのサービスはclassによって以下のように分類される.
    class core:
    
    
    
    service ueventd /sbin/ueventd
    
    service console /system/bin/sh
    
    service adbd /sbin/adbd
    
    service servicemanager /system/bin/servicemanager
    
    service vold /system/bin/vold
    
    
    
    
    
    class main:
    
    
    
    service netd /system/bin/netd
    
    service debuggerd /system/bin/debuggerd
    
    service ril-daemon /system/bin/rild
    
    service surfaceflinger /system/bin/surfaceflinger
    
    service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    
    service drm /system/bin/drmserver
    
    service media /system/bin/mediaserver
    
    service bootanim /system/bin/bootanimation
    
    service dbus /system/bin/dbus-daemon --system --nofork
    
    service bluetoothd /system/bin/bluetoothd -n
    
    service installd /system/bin/installd
    
    service flash_recovery /system/etc/install-recovery.sh
    
    service racoon /system/bin/racoon
    
    service mtpd /system/bin/mtpd
    
    service keystore /system/bin/keystore /data/misc/keystore
    
    service dumpstate /system/bin/dumpstate -s

    Serviceueventd:読み込み/ueventd.rcおよび/ueventd.$hadrware.rcファイル、解析とinit.rc解析は同様で、主にファイルシステムの権限とユーザーを設定します:(コード:system/core/init/ueventd.c)
    #      user group

    /dev/null 0666 root root /dev/zero 0666 root root

    class coreサービスが起動した後、class mainが起動し始め、service zygoteはandroidに入る最も重要なサービスであり、サービス名zygoteは、実際に起動したのはapp_である.process,(コード:frameworks/base/cmds/app_process/app_main.cpp)
    int main(int argc, const char* const argv[])
    
    {
    
        // These are global variables in ProcessState.cpp
    
        mArgC = argc;
    
        mArgV = argv;
    
    
    
        mArgLen = 0;

    // , init.rc : -Xzygote /system/bin --zygote --start-system-server
    for (int i=0; i<argc; i++) { mArgLen += strlen(argv[i]) + 1; } mArgLen--; AppRuntime runtime; const char* argv0 = argv[0]; //-Xzygote // Process command line arguments // ignore argv[0] argc--; // 4, 3 argv++; //argv argv[1] // Everything up to '--' or first non '-' arg goes to the vm   
       // i = 0, :frameworks/base/core/jni/AndroidRuntime.cpp int i = runtime.addVmArguments(argc, argv); // Parse runtime arguments. Stop at first unrecognized option. bool zygote = false; bool startSystemServer = false; bool application = false; const char* parentDir = NULL; const char* niceName = NULL; const char* className = NULL; while (i < argc) { const char* arg = argv[i++]; if (!parentDir) { parentDir = arg;               //parentDir = /system/bin } else if (strcmp(arg, "--zygote") == 0) { // i = 2,arg = argv[1] , :--zygote zygote = true;                 niceName = "zygote"; } else if (strcmp(arg, "--start-system-server") == 0) { startSystemServer = true; } else if (strcmp(arg, "--application") == 0) { application = true; } else if (strncmp(arg, "--nice-name=", 12) == 0) { niceName = arg + 12; } else { className = arg; break; } } if (niceName && *niceName) { setArgv0(argv0, niceName); set_process_name(niceName); } runtime.mParentDir = parentDir; if (zygote) {
         // zygote = true, com.android.internal.os.ZygoteInit, :startSystemServer runtime.start(
    "com.android.internal.os.ZygoteInit",startSystemServer ? "start-system-server" : ""); } else if (className) { // Remainder of args get passed to startup class main() runtime.mClassName = className; runtime.mArgC = argc - i; runtime.mArgV = argv + i; runtime.start("com.android.internal.os.RuntimeInit", application ? "application" : "tool"); } else { fprintf(stderr, "Error: no class name or --zygote supplied.
    "); app_usage(); LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); return 10; } }

    入力パラメータが検出され、次のように呼び出されます.
     runtime.start("com.android.internal.os.ZygoteInit",startSystemServer ? "start-system-server" : "");

    runtimeのコード:frameworks/base/core/jni/Android Runtime.cpp,start関数は仮想マシンを起動しcomを実行する.android.internal.os.ZygoteInitクラスのmain関数で、パラメータ:start-system-server:
    void AndroidRuntime::start(const char* className, const char* options)
    
    {
    
        LOGD("
    >>>>>> AndroidRuntime START %s <<<<<<
    ", className != NULL ? className : "(unknown)");
    ...
    /* start the virtual machine */
    // dalvik ,
    JNIEnv* env; if (startVm(&mJavaVM, &env) != 0) { return; } onVmCreated(env); /* * Register android functions. */ if (startReg(env) < 0) { LOGE("Unable to register all android natives
    "); return; } ...
    /* * Start VM. This thread becomes the main thread of the VM, and will * not return until the VM exits. */
    // com.xxx.xxx com/xxx/xxx char* slashClassName = toSlashClassName(className); jclass startClass = env->FindClass(slashClassName); if (startClass == NULL) { LOGE("JavaVM unable to locate class '%s'
    ", slashClassName); /* keep going */ } else {
         // jni java , class, main jmethodID startMeth
    = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V"); if (startMeth == NULL) { LOGE("JavaVM unable to find main() in '%s'
    ", className); /* keep going */ } else { env->CallStaticVoidMethod(startClass, startMeth, strArray); } } free(slashClassName); LOGD("Shutting down VM
    "); if (mJavaVM->DetachCurrentThread() != JNI_OK) LOGW("Warning: unable to detach main thread
    "); if (mJavaVM->DestroyJavaVM() != 0) LOGW("Warning: VM did not shut down cleanly
    "); }

    ZygoteInitクラスmain関数:
     public static void main(String argv[]) {
    
            try {
    
                // Start profiling the zygote initialization.
    
                SamplingProfilerIntegration.start();
    
           
    // socket server registerZygoteSocket(); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis());

    // , preloadClasses() preloadResources(), /system/etc/event-log-tags preload(); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis());        
     
    // Finish profiling the zygote initialization. SamplingProfilerIntegration.writeZygoteSnapshot(); // Do an initial gc to clean up after startup gc(); // If requested, start system server directly from Zygote if (argv.length != 2) { throw new RuntimeException(argv[0] + USAGE_STRING); }    if (argv[1].equals("start-system-server")) {
              // Zygote main , start-system-server, startSystemServer() startSystemServer(); }
    else if (!argv[1].equals("")) { throw new RuntimeException(argv[0] + USAGE_STRING); } Log.i(TAG, "Accepting command socket connections"); if (ZYGOTE_FORK_MODE) { runForkMode(); } else {
             // registerZygoteSocket() server scocket, , Zygote runSelectLoopMode(); }          closeServerSocket(); }
    catch (MethodAndArgsCaller caller) { caller.run(); } catch (RuntimeException ex) { Log.e(TAG, "Zygote died with exception", ex); closeServerSocket(); throw ex; } }

     
    ではstartSystemServerはいったい何をしているのか、そして最後のシステムはどのようにACTIONを発行しているのか.BOOT_COMPLETEDが放送されていて、次回の分解を聞いています.-):