編輯:關於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 AndroidRuntimeandroidruntime是怎麼樣的呢?裡面有沒有start的方法呢?
AndroidRunTime的實現位於:frameworks/base/core/jni/AndroidRuntime.cpp
我們從裡面找到了start的方法。
951void AndroidRuntime::start(const char* className, const Vector來根據剛才傳遞的參數來看一下zygoteInit的main函數& 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}
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循環,來處理後續的請求。
國產手機的集體高潮,卻使消費者變的“煩惱了”,因為消費者在購買手機時變得越來越猶豫糾結。以2499元這個價位的手機來說,單國產手機就
#####################################################################################
在看本文之前,如果你對於Android的廣播機制不是很了解,建議先行閱讀我轉載的一篇博文:圖解 Android 廣播機制。 由於本案例比較簡單,故直接在此貼出代碼,不做
MainActivity如下:package cc.testview4; import cc.testview4.SlideView.SwitchChangedList