Android本地服務的啟動 – zygote服務及Dalvik環境啟動

來源:互聯網
上載者:User

通過上一節Android init進程啟動的分析可知,init進程在啟動過程中,解析並處理了init.rc和init.hardware.rc兩個初始化指令檔,在兩個初始化指令檔裡,定義了一系列的service section,這些service在boot觸發器下,通過class_start
default依次啟動,其過程總結如下:

    1. init 解析init.rc

    2. init 將init.rc裡的service放到隊列裡面等待觸發器的觸發

    3. init通過 action_for_each_trigger("boot", action_add_queue_tail);觸發boot Action

    4. 依次執行boot下的Commands,包括class_start default命令

    5. 所有的service預設的class為預設值:default,所以,所有init.rc中的service都被啟動

zygote服務啟動


通過init.rc中對zygote服務的描述可知,其對應的程式為:/system/bin/app_process

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
    socket zygote stream 666
    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media

該服務會在on boot時觸發,其程式為/system/bin/app_process,服務名為zygote,-Xzygote /system/bin --zygote
--start-system-server為參數列表。

在建立了zygote 服務後,在目錄下建立一個stream socket檔案/dev/socket/zygote,許可權為666,當zygote服務重啟時,重啟media服務

通過find ./ -name Android.mk  -exec grep -l app_process {} \; 命令,尋找到,它在./frameworks/base/cmds/app_process/目錄中被編譯,其主要入口檔案為:

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

找到該程式的main入口函數,

118 int main(int argc, const char* const argv[])
119 {
120     // These are global variables in ProcessState.cpp
121     mArgC = argc;
122     mArgV = argv;
123
124     mArgLen = 0;
125     for (int i=0; i<argc; i++) {
126         mArgLen += strlen(argv[i]) + 1;
127     }
128     mArgLen--;
129
130     AppRuntime runtime;
131     const char *arg;
132     const char *argv0;
133
134     argv0 = argv[0];
135
136     // Process command line arguments
137     // ignore argv[0]
138     argc--;
139     argv++;

141     // Everything up to '--' or first non '-' arg goes to the vm
142     // 在zygote服務的參數列表中,以‘--和非‘-’開頭的參數,是dalvik的參數:/system/bin--zygote --start-system-server,交給Vm來處理

143     int i = runtime.addVmArguments(argc, argv);
144
145     // 找到zygote的目錄:/system/bin
146     if (i < argc) {
147         runtime.mParentDir = argv[i++];
148     }
149
150     // 如果接下來的參數是:--zygote --start-system-server的話,設定argv0=“zygote”,startSystemServer= true,啟動java VM
151     if (i < argc) {
152         arg = argv[i++];
153         if (0 == strcmp("--zygote", arg)) {
154             bool startSystemServer = (i < argc) ?
155                     strcmp(argv[i], "--start-system-server") == 0 : false;
156             setArgv0(argv0, "zygote");
157             set_process_name("zygote");
158             runtime.start("com.android.internal.os.ZygoteInit",
159                 startSystemServer);
160         } else {
161             set_process_name(argv0);
162
163             runtime.mClassName = arg;
164
165             // Remainder of args get passed to startup class main()
166             runtime.mArgC = argc-i;

167             runtime.mArgV = argv+i;
168
169             LOGV("App process is starting with pid=%d, class=%s.\n",
170                  getpid(), runtime.getClassName());
171             runtime.start();
172         }
173     } else {
174         LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
175         fprintf(stderr, "Error: no class name or --zygote supplied.\n");
176         app_usage();
177         return 10;
178     }
179
180 }

 根據service zygote的參數,啟動VM:

runtime.start("com.android.internal.os.ZygoteInit", startSystemServer);

runtime是AppRuntime的對象,AppRuntime是AndroidRuntime的子類:

runtime.start方法在AndroidRuntime裡實現:

 859 void AndroidRuntime::start(const char* className, const bool startSystemServer)
 860 {
 861     LOGD("\n>>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<<\n");  // logcat裡最顯眼的字樣
 862
 863     char* slashClassName = NULL;
 864     char* cp;
 865     JNIEnv* env;
 866
 867     blockSigpipe();
 868
 869     /*
 870      * 'startSystemServer == true' means runtime is obslete and not run from
 871      * init.rc anymore, so we print out the boot start event here.
 872      */
 873     if (startSystemServer) {
 874         /* track our progress through the boot sequence */
 875         const int LOG_BOOT_PROGRESS_START = 3000;
 876         LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
 877                        ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
 878     }

 880     const char* rootDir = getenv("ANDROID_ROOT");  // 取得Android的根目錄:/system
 881     if (rootDir == NULL) {
 882         rootDir = "/system";
 883         if (!hasDir("/system")) {
 884             LOG_FATAL("No root directory specified, and /android does not exist.");
 885             goto bail;
 886         }
 887         setenv("ANDROID_ROOT", rootDir, 1);
 888     }
 889
 890     //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
 891     //LOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
 892
 893     /* start the virtual machine */

// 啟動Dalvik虛擬機器,在AndroidRuntime::startVm方法中,裝置了大量VM的參數,最後調用JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs),通過JNI啟動虛擬機器
 894     if (startVm(&mJavaVM, &env) != 0)     

 895         goto bail;
 896
 897     /*
 898      * Register android functions.
 899      */
 900     if (startReg(env) < 0) {      // 註冊系統使用的JNI函數
 901         LOGE("Unable to register all android natives\n");
 902         goto bail;
 903     }

 910     jclass stringClass;
 911     jobjectArray strArray;
 912     jstring classNameStr;
 913     jstring startSystemServerStr;
 914
 915     stringClass = env->FindClass("java/lang/String");          // 從Dalvik虛擬機器裡,尋找到String類,
 916     assert(stringClass != NULL);
 917     strArray = env->NewObjectArray(2, stringClass, NULL); 
// 建立一個String數組,有兩個元素(strArray =  new String[2])
 918     assert(strArray != NULL);
 919     classNameStr = env->NewStringUTF(className);       // 建立一個Java String對象,初始值為:className,其實是start第一個參數:com.android.internal.os.ZygoteInit
 920     assert(classNameStr != NULL);
 921     env->SetObjectArrayElement(strArray, 0, classNameStr);  
// 設定strArray 第一個元素的值為:classNameStr (strArray[0] =classNameStr)
 922     startSystemServerStr = env->NewStringUTF(startSystemServer ?
 923                                                  "true" : "false");   //
建立一個Java String對象,初始值為:startSystemServer ,其實是start第二個參數:true
 924     env->SetObjectArrayElement(strArray, 1, startSystemServerStr);
// 設定strArray 第二個元素的值為:strArray[1] =startSystemServerStr

 925
 926     /*
 927      * Start VM.  This thread becomes the main thread of the VM, and will
 928      * not return until the VM exits.
 929      */

          // 根據上面的解釋可知:準備啟動Java VM,並且建立VM的主線程,只要VM不退出,這個主線程一直運行。
 930     jclass startClass;
 931     jmethodID startMeth;

 933     slashClassName = strdup(className);
 934     for (cp = slashClassName; *cp != '\0'; cp++)    // 將com.android.internal.os.ZygoteInit中的包分隔字元‘.’換成‘/’即:com/android/internal/os/ZygoteInit
 935         if (*cp == '.')
 936             *cp = '/';
 937
 938     startClass = env->FindClass(slashClassName);  
// 從VM中尋找ZygoteInit類,難道它要在VM裡載入這個類。。。。
 939     if (startClass == NULL) {
 940         LOGE("JavaVM unable to locate class '%s'\n", slashClassName);
 941         /* keep going */
 942     } else {
 943         startMeth = env->GetStaticMethodID(startClass, "main",
 944             "([Ljava/lang/String;)V");  
// 尋找到com/android/internal/os/ZygoteInit類中的main方法ID,接合Java檔案命名規則,你能更深刻的理解,為什麼主類名要和檔案名稱一致,並且main方法為static方法。
 945         if (startMeth == NULL) {
 946             LOGE("JavaVM unable to find main() in '%s'\n", className);
 947             /* keep going */
 948         } else {
 949             env->CallStaticVoidMethod(startClass, startMeth, strArray);  // 調用ZygoteInit類裡的main方法,這不是運行ZygoteInit這個JAVA程式嗎!!
 950
 951 #if 0
 952             if (env->ExceptionCheck())
 953                 threadExitUncaughtException(env);
 954 #endif
 955         }
 956     }

 957
 958     LOGD("Shutting down VM\n");
 959     if (mJavaVM->DetachCurrentThread() != JNI_OK)
 960         LOGW("Warning: unable to detach main thread\n");
 961     if (mJavaVM->DestroyJavaVM() != 0)
 962         LOGW("Warning: VM did not shut down cleanly\n");
 963
 964 bail:
 965     free(slashClassName);
 966 }
 967
由上面的分析可知,AndroidRuntime::start方法實現了下面功能:

  1> 通過startVm來啟動虛擬機器,並且註冊了一些系統JNI函數,由於這個時候VM裡還沒有程式,只是個空的VM執行環境

  2> 通過AndroidRuntime::start的參數,在JNI代碼裡構建第一個Java程式ZygoteInit,將其作為VM的主線程,同時給其傳遞兩個JNI構建的參數:

       "com/android/internal/os/ZygoteInit"和"true"

總結:

Android系統的啟動是由init進程載入並啟動了裡面的/system/bin/app_process程式作為zygote服務,然後在zygote服務裡執行runtime.start啟動Dalvik虛擬機器,載入了ZygoteInit類作為Dalvik虛擬機器的第一個主線程。至此,Android的Java運行環境就準備完畢了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.