Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android啟動流程分析- zygote的啟動

Android啟動流程分析- zygote的啟動

編輯:關於Android編程

 

前面的文章花了很大的篇幅去介紹了init進程如何去解析init.rc,如何去執行系統的一些服務。

那麼,我們所說的zygote是怎麼啟動的呢?zygote又是具體負責了哪些工作呢?

本文我們來一探究竟。

zygote在inir.rc中有如下的描述:

 

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    class main
    socket zygote stream 660 root system
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media
    onrestart restart netd
我們可以簡單的分析下這兩句話,

 

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

class main

這個是說,zygote是屬於main的class。

zygote是一個服務,服務的名字叫zygote. 啟動的時候執行的命令是app_process, 傳遞的參數是-Xzygote /system/bin --zygote --start-system-server

那麼,按照我們前面分析的理論,我們去看一下app_process是個什麼東西
首先我們到framework的目錄下,在base/cmds/app_process裡面,我們看到了生成app_process的makefile

 

include $(CLEAR_VARS)

LOCAL_SRC_FILES:= 
        app_main.cpp

LOCAL_SHARED_LIBRARIES := 
        libcutils 
        libutils 
        liblog 
        libbinder 
        libandroid_runtime

LOCAL_MODULE:= app_process
LOCAL_MULTILIB := both
LOCAL_MODULE_STEM_32 := app_process32
LOCAL_MODULE_STEM_64 := app_process64
include $(BUILD_EXECUTABLE)
我們可以看到app_process被執行生成了一個應用程序。

 

試想一下,zygote的這個服務應該是一直在運行的,但是我們如果adb shell去看ps的話,並找不到app_process的這個命令在一直運行。

這個是為什麼呢?

 

首先我們從app_process的main函數裡面截取出來一段

 

    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, --zygote) == 0) { // 如果從init.rc裡面傳進來的參數是帶--zygote的話,一定是會進這個判斷
            zygote = true;  // 將zygote設置為true
            niceName = ZYGOTE_NICE_NAME;  // 將niceName設置為zygote_nice_name設置為zygote
        } else if (strcmp(arg, --start-system-server) == 0) { // 如果是要啟動start-system-server的話
            startSystemServer = true; // 會將startsystemserver設置為true
        } else if (strcmp(arg, --application) == 0) {  // 
            application = true;
        } else if (strncmp(arg, --nice-name=, 12) == 0) {
            niceName.setTo(arg + 12);
        } else if (strncmp(arg, --, 2) != 0) {
            className.setTo(arg);
            break;
        } else {
            --i;
            break;
        }
    }

 

然後這幾個參數可以怎麼去使用呢?

接著看一下後面的代碼,是如何使用的。

 

    if (!niceName.isEmpty()) {  //如果niceName不為空的話
        runtime.setArgv0(niceName.string());
        set_process_name(niceName.string()); // 調用這個函數將這個process的name設置為zygote
    }

    if (zygote) { // zygote一定為true
        runtime.start(com.android.internal.os.ZygoteInit, args); //我們進入到了這個判斷
    } else if (className) {
        runtime.start(com.android.internal.os.RuntimeInit, args);
    } 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的方法區進行了這個zygote的啟動的工作,那麼我們這個runtime是調用的哪邊的start呢?

 

我們在當前的appruntime裡面,是沒有相關start函數的實現。

那我們去他的父類裡面去看一下。

 

class AppRuntime : public AndroidRuntime
androidruntime是怎麼樣的呢?裡面有沒有start的方法呢?

 

AndroidRunTime的實現位於:frameworks/base/core/jni/AndroidRuntime.cpp

我們從裡面找到了start的方法。

 

951void AndroidRuntime::start(const char* className, const Vector& options)
952{
953    ALOGD(>>>>>> START %s uid %d <<<<<<
,
954            className != NULL ? className : (unknown), getuid());
955
956    static const String8 startSystemServer(start-system-server);
957
958    /*
959     * 'startSystemServer == true' means runtime is obsolete and not run from
960     * init.rc anymore, so we print out the boot start event here.
961     */
962    for (size_t i = 0; i < options.size(); ++i) {
963        if (options[i] == startSystemServer) {
964           /* track our progress through the boot sequence */
965           const int LOG_BOOT_PROGRESS_START = 3000;
966           LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,  ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
967        }
968    }
969
970    const char* rootDir = getenv(ANDROID_ROOT);
971    if (rootDir == NULL) {
972        rootDir = /system;
973        if (!hasDir(/system)) {
974            LOG_FATAL(No root directory specified, and /android does not exist.);
975            return;
976        }
977        setenv(ANDROID_ROOT, rootDir, 1);
978    }
979
980    //const char* kernelHack = getenv(LD_ASSUME_KERNEL);
981    //ALOGD(Found LD_ASSUME_KERNEL='%s'
, kernelHack);
982
983    /* start the virtual machine */
984    JniInvocation jni_invocation;
985    jni_invocation.Init(NULL);
986    JNIEnv* env;
987    if (startVm(&mJavaVM, &env) != 0) {    // 創建虛擬機
988        return;
989    }
990    onVmCreated(env);
991
992    /*
993     * Register android functions.
994     */
995    if (startReg(env) < 0) { // 注冊jni的方法
996        ALOGE(Unable to register all android natives
);
997        return;
998    }
999
1000    /*
1001     * We want to call main() with a String array with arguments in it.
1002     * At present we have two arguments, the class name and an option string.
1003     * Create an array to hold them.
1004     */
1005    jclass stringClass;  // class對象
1006    jobjectArray strArray; // 對應objectArray對象
1007    jstring classNameStr; // 一個string
1008
1009    stringClass = env->FindClass(java/lang/String); //首先找到了string的class
1010    assert(stringClass != NULL);
1011    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);  // New 了一個ObjectArray
1012    assert(strArray != NULL);
1013    classNameStr = env->NewStringUTF(className);  // 將className轉換為UTF8的類型
1014    assert(classNameStr != NULL);
1015    env->SetObjectArrayElement(strArray, 0, classNameStr);  // 設置objectarray的第一個元素為classname
1016
1017    for (size_t i = 0; i < options.size(); ++i) {  // 將後續的參數依次經過轉換push到strArray的數組中
1018        jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
1019        assert(optionsStr != NULL);
1020        env->SetObjectArrayElement(strArray, i + 1, optionsStr);
1021    }
1022
1023    /*
1024     * Start VM.  This thread becomes the main thread of the VM, and will
1025     * not return until the VM exits.
1026     */
1027    char* slashClassName = toSlashClassName(className); // 將className轉換為/的形式
1028    jclass startClass = env->FindClass(slashClassName); // 尋找這個類
1029    if (startClass == NULL) { // 如果找不到的話,我們會返回NULL
1030        ALOGE(JavaVM unable to locate class '%s'
, slashClassName);
1031        /* keep going */
1032    } else {
1033        jmethodID startMeth = env->GetStaticMethodID(startClass, main,
1034            ([Ljava/lang/String;)V);   // 獲取我們尋找到的這個類的main函數
1035        if (startMeth == NULL) {
1036            ALOGE(JavaVM unable to find main() in '%s'
, className);
1037            /* keep going */
1038        } else {
1039            env->CallStaticVoidMethod(startClass, startMeth, strArray); // 去執行這個類的main函數的方法。
1040
1041#if 0
1042            if (env->ExceptionCheck())
1043                threadExitUncaughtException(env);
1044#endif
1045        }
1046    }
1047    free(slashClassName);  // free
1048
1049    ALOGD(Shutting down VM
);
1050    if (mJavaVM->DetachCurrentThread() != JNI_OK)
1051        ALOGW(Warning: unable to detach main thread
);
1052    if (mJavaVM->DestroyJavaVM() != 0)
1053        ALOGW(Warning: VM did not shut down cleanly
);
1054}
來根據剛才傳遞的參數來看一下zygoteInit的main函數

 

 

648    public static void main(String argv[]) {
649        try {
650            // Start profiling the zygote initialization.
651            SamplingProfilerIntegration.start();
652
653            boolean startSystemServer = false;
654            String socketName = zygote;
655            String abiList = null;
656            for (int i = 1; i < argv.length; i++) {
657                if (start-system-server.equals(argv[i])) {
658                    startSystemServer = true;  // startSystemServer為true
659                } else if (argv[i].startsWith(ABI_LIST_ARG)) {
660                    abiList = argv[i].substring(ABI_LIST_ARG.length());
661                } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
662                    socketName = argv[i].substring(SOCKET_NAME_ARG.length());
663                } else {
664                    throw new RuntimeException(Unknown command line argument:  + argv[i]);
665                }
666            }
667
668            if (abiList == null) {
669                throw new RuntimeException(No ABI list supplied.);
670            }
671
672            registerZygoteSocket(socketName); // 注冊了一個socket,用來與系統中的其他應用程序進行通信
673            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
674                SystemClock.uptimeMillis());
675            preload(); // 預加載一些資源
676            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
677                SystemClock.uptimeMillis());
678
679            // Finish profiling the zygote initialization.
680            SamplingProfilerIntegration.writeZygoteSnapshot();
681
682            // Do an initial gc to clean up after startup
683            gc();
684
685            // Disable tracing so that forked processes do not inherit stale tracing tags from
686            // Zygote.
687            Trace.setTracingEnabled(false);
688
689            if (startSystemServer) {  // 如果startSystemServer為true的話,我們會啟動systemServer
690                startSystemServer(abiList, socketName);
691            }
692
693            Log.i(TAG, Accepting command socket connections);
694            runSelectLoop(abiList);  // 進入select的循環,用來響應其他應用程序的請求
695
696            closeServerSocket();
697        } catch (MethodAndArgsCaller caller) {
698            caller.run();
699        } catch (RuntimeException ex) {
700            Log.e(TAG, Zygote died with exception, ex);
701            closeServerSocket();
702            throw ex;
703        }
704    }
那麼,最後我們對zygote進行一下總結

 

首先zygote創建了appruntime的對象,並調用他的start。此後的活動由AppRuntime來控制

然後調用startVM來創建了虛擬機,調用startReg來注冊JNI的函數

通過JNI調用zygoteInit進入了java的世界

調用registerZygoteSocket來響應子孫後代的請求,同時調用preload函數進行資源的預加載

調用startSystemServer來進行系統啟動的後續工作

完成了java世界的初創工作後,變進入了select循環,來處理後續的請求。

 





 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved