詳細(xì)分析Android中實(shí)現(xiàn)Zygote的源碼
概述
在Android系統(tǒng)中,所有的應(yīng)用程序進(jìn)程,以及用來(lái)運(yùn)行系統(tǒng)關(guān)鍵服務(wù)的System進(jìn)程都是由zygote進(jìn)程負(fù)責(zé)創(chuàng)建的。因此,我們將它稱為進(jìn)程孵化器。zygote進(jìn)程是通過(guò)復(fù)制自身的方式來(lái)創(chuàng)建System進(jìn)程和應(yīng)用程序進(jìn)程的。由于zygote進(jìn)程在啟動(dòng)時(shí)會(huì)在內(nèi)部創(chuàng)建一個(gè)虛擬機(jī)實(shí)例,因此,通過(guò)復(fù)制zygote進(jìn)程而得到的System進(jìn)程和應(yīng)用程序進(jìn)程可以快速地在內(nèi)部獲得一個(gè)虛擬機(jī)實(shí)例拷貝。
zygote進(jìn)程在啟動(dòng)完成之后,會(huì)馬上將System進(jìn)程啟動(dòng)起來(lái),以便它可以將系統(tǒng)的關(guān)鍵服務(wù)啟動(dòng)起來(lái)。下面我們將介紹zygote進(jìn)程的啟動(dòng)腳本,然后分析它和System進(jìn)程的啟動(dòng)過(guò)程。
zygote分析
zygote進(jìn)程的啟動(dòng)腳本如下:
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
在我之前的一篇博客中已經(jīng)分析了init進(jìn)程是如何啟動(dòng)service服務(wù)了,需要了解的同學(xué)可以參考這篇文章:Android init進(jìn)程——解析配置文件
通過(guò)zygote服務(wù)的啟動(dòng)腳本,我們可以知道,zygote進(jìn)程的實(shí)際是二進(jìn)制文件app_process的調(diào)用,我們就從這個(gè)應(yīng)用程序的main函數(shù)入手去分析一下zygote進(jìn)程的啟動(dòng)過(guò)程,源碼如下(/frameworks/base/cmds/app_process/app_main.cpp):
/** * 將-Xzygote加入到JavaVMOption中,返回/system/bin參數(shù)指向的下標(biāo) */ int AndroidRuntime::addVmArguments(int argc, const char* const argv[]) { int i; for (i = 0; i < argc; i ++) { if (argv[i][0] != '-') { return i; } if (argv[i][1] == '-' && argv[i][2] == 0) { return i + 1; } JavaVMOption opt; memset(&opt, 0, sizeof(opt)); opt.optionString = (char*)argv[i]; mOptions.add(opt); } return i; } int main(int argc, char* const argv[]) { // zygote call parameters // /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server // These are global variables in ProcessState.cpp mArgC = argc; mArgV = argv; mArgLen = 0; for (int i = 0; i < argc; i ++) { mArgLen += strlen(argv[i]) + 1; } // 去除末尾的空格 mArgLen--; AppRuntime runtime; const char* argv0 = argv[0]; // Process command line arguments // ignore argv[0] argc --; argv ++; // Everything up tp '--' or first non '-' arg goes to the vm 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; } else if (strcmp(arg, "--zygote") == 0) { 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)) { niceName = arg + 12; } else { className = arg; break; } } if (niceName && *niceName) { setArgv0(argv0, niceName); set_process_name(niceName); } runtime.mParentDir = parentDir; if (zygote) { // 進(jìn)入到AppRuntime的start函數(shù) runtime.start("com.android.internal.os.ZygoteInit", startSystemServer? "start-system-server" : ""); } else if (className) { 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.\n"); app_usage(); LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied"); return 10; } }
在zygote的main函數(shù)中,通過(guò)AppRuntime runtime代碼創(chuàng)建了一個(gè)AppRuntime對(duì)象runtime,接下來(lái)Zygote進(jìn)程就是通過(guò)它來(lái)進(jìn)一步啟動(dòng)的。
init.rc中關(guān)于啟動(dòng)zygote命令中包含了–zygote參數(shù),所以在if(strcmp(arg, “–zygote”) == 0)判斷的時(shí)候,會(huì)將niceName賦值為”zygote”,然后通過(guò)set_process_name(niceName)函數(shù)將當(dāng)前進(jìn)程的名稱設(shè)置為zygote。這也是為什么調(diào)用的腳本為/system/bin/app_process,而進(jìn)程名為zygote的原因。set_process_name函數(shù)的源碼如下(/system/core/libcutils/process_name.c):
static const char* process_name = "unknown"; void set_process_name(const char* new_name) { if (new_name == NULL) { return; } int len = strlen(new_name); char* copy = (char*)malloc(len + 1); strcpy(copy, new_name); process_name = (const char*) copy; }
從init.rc文件中關(guān)于zygote進(jìn)程的配置參數(shù)可知,Zygote進(jìn)程傳遞給應(yīng)用程序app_process的啟動(dòng)參數(shù)arg還包含一個(gè)”–start-system-server”選項(xiàng)。因此,在調(diào)用AppRuntime對(duì)象runtime的成員函數(shù)start時(shí),第二個(gè)參數(shù)為”start-system-server”,表示zygote進(jìn)程啟動(dòng)完成之后,需要將system進(jìn)程啟動(dòng)起來(lái)。
AppRuntime分析
AppRuntime類的成員函數(shù)start是從父類AndroidRuntime繼承下來(lái)的,因此,接下來(lái)我們就繼續(xù)分析AndroidRuntime類的成員函數(shù)start的實(shí)現(xiàn),函數(shù)源碼位置:/frameworks/base/core/jni/AndroidRuntime.cpp:
char* AndroidRuntime::toSlashClassName(const char* className) { char* result = strdup(className); for (char* cp = result; *cp != '\0'; cp ++) { if (*cp == '.') { *cp = '/'; } } return result; } /** * Start the Android runtime. This involves starting the virtual machine * and calling the "static void main(String[] args)" method int the class * named by "className". * * 這兩個(gè)參數(shù)的值分別為: * const char* className = "com.android.internal.os.ZygoteInit"; * const char* options = "start-system-server"; */ void AndroidRuntime::start(const char* className, const char* options) { ALOGD("\n>>>>> AndroidRuntime START %s <<<<<<\n", className != NULL ? className : "(unknown)"); /** * 'startSystemServer == true' means runtime is obsolete and not run from * init.rc anymore, so we print out the boot start event here. */ if (strcmp(options, "start-system-server") == 0) { const int LOG_BOOT_PROGRESS_START = 3000; LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC))); } // 設(shè)置ANDROID_ROOT環(huán)境變量 const char* rootDir = getenv("ANDROID_ROOT"); if (rootDir == NULL) { rootDir = "/system"; if (!hasDir("/system")) { LOG_FATAL("No root directory specified, and /android dose not exist."); return; } setenv("ANDROID_ROOT", rootDir, 1); } JniInvocation jni_invocation; jni_invocation.Init(NULL); JNIEnv* env; // 1. 創(chuàng)建虛擬機(jī) if (startVm(&mJavaVM, &env) != 0) { return; } onVmCreated(env); // 2. 注冊(cè)JNI函數(shù) if (startReg(env) < 0) { ALOGE("Unable to register all android natives\n"); return; } jclass stringClass; jobjectArray strArray; jstring classNameStr; jstring optionsStr; stringClass = env->FindClass("java/lang/String"); assert(stringClass != NULL); // 創(chuàng)建一個(gè)有兩個(gè)元素的String數(shù)組,用Java代碼表示為:String[] strArray = new String[2]; strArray = env->NewObjectArray(2, stringClass, NULL); assert(strArray != NULL); classNameStr = env->NewStringUTF(className); assert(classNameStr != NULL); // 設(shè)置第一個(gè)元素為"com.android.internal.os.ZygoteInit" env->SetObjectArrayElement(strArray, 0, classNameStr); optionsStr = env->NewStringUTF(options); // 設(shè)置第二個(gè)元素為"start-system-server" env->SetObjectArrayElement(strArray, 1, optionsStr); // 將字符串"com.android.internal.os.ZygoteInit"轉(zhuǎn)換為"com/android/internal/os/ZygoteInit" char* slashClassName = toSlashClassName(className); jclass startClass = env->FindClass(slashClassName); if (startClass == NULL) { ALOGE("JavaVM unable to locate class '%s'\n", slashClassName); } else { jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V"); if (startMeth == NULL) { ALOGE("JavaVM unable to find main() in '%s\n'", className); } else { // 3. // 通過(guò)JNI調(diào)用java函數(shù),注意調(diào)用的是main函數(shù),所屬的類是"com.android.internal.os.ZygoteInit". // 傳遞的參數(shù)是"com.android.internal.os.ZygoteInit true" env->CallStaticVoidMethod(startClass, startMeth, strArray); } } free(slashClassName); ALOGD("Shutting down VM\n"); if (mJavaVM->DetachCurrentThread() != JNI_OK) { ALOGW("Warning: unable to detach main thread\n"); } if (mJavaVM->DestoryJavaVM() != 0) { ALOGW("Warning: VM did not shut down cleanly\n"); } }
上述代碼有幾處關(guān)鍵點(diǎn),分別是:
- 創(chuàng)建虛擬機(jī)。
- 注冊(cè)JNI函數(shù)。
- 進(jìn)入Java世界。
接下來(lái),我們分別分析這三個(gè)關(guān)鍵點(diǎn)。
創(chuàng)建虛擬機(jī)——startVm
startVm并沒有特別之處,就是調(diào)用JNI的虛擬機(jī)創(chuàng)建函數(shù),但是創(chuàng)建虛擬機(jī)時(shí)的一些參數(shù)卻是在startVm中確定的,其源碼如下:
#define PROPERTY_VALUE_MAX 92 /** * Start the Dalvik Virtual Machine. * * Various arguments, most determined by system properties, are passed in. * The "mOptions" vector is updated. * * Returns 0 on success. */ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIENV** pEnv) { int result = -1; JavaVMInitArgs initArgs; JavaVMOption opt; char propBuf[PROPERTY_VALUE_MAX]; char stackTraceFileBuf[PROPERTY_VALUE_MAX]; char dexoptFlagsBuf[PROPERTY_VALUE_MAX]; char enableAssertBuf[sizeof("-ea:")-1 + PROPERTY_VALUE_MAX]; char jniOptsBuf[sizeof("-Xjniopts:")-1 + PROPERTY_VALUE_MAX]; char heapstartsizeOptsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX]; char heapsizeOptsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX]; char heapgrowthlimitOptsBuf[sizeof("-XX:HeapGrowthLimit=")-1 + PROPERTY_VALUE_MAX]; char heapminfreeOptsBuf[sizeof("-XX:HeapMinFree=")-1 + PROPERTY_VALUE_MAX]; char heapmaxfreeOptsBuf[sizeof("-XX:HeapMaxFree=")-1 + PROPERTY_VALUE_MAX]; char heaptargetutilizationOptsBuf[sizeof("-XX:HeapTargetUtilization=")-1 + PROPERTY_VALUE_MAX]; char jitcodecachesizeOptsBuf[sizeof("-Xjitcodecachesize:")-1 + PROPERTY_VALUE_MAX]; char extraOptsBuf[PROPERTY_VALUE_MAX]; char* stackTraceFile = NULL; bool checkJni = false; bool checkDexSum = false; bool logStdio = false; enum { KEMDefault, KEMIntPortable, KEMIntFast, KEMJitCompiler, } executionMode = KEMDefault; /** * 這段代碼是用了設(shè)置JNI_check選項(xiàng)的。JNI_check指的是Native層調(diào)用JNI函數(shù)時(shí),系統(tǒng)所做的一些檢查動(dòng)作。 * 這個(gè)選項(xiàng)雖然能增加可靠性,但是還有一些副作用: * 1. 因?yàn)闄z查工作比較耗時(shí),所以會(huì)影響系統(tǒng)運(yùn)行速度。 * 2. 有些檢查工作比較耗時(shí),一旦出錯(cuò),整個(gè)進(jìn)程會(huì)abort。 * 所以,JNI_check選項(xiàng)一般只在eng版本設(shè)置。 */ property_get("dalvik.vm.checkjni", propBuf, ""); if (strcmp(propBuf, "true") == 0) { checkJni = true; } else if (strcmp(propBuf, "false") != 0) { property_get("ro.kernel.android.checkjni", propBuf, ""); if (propBuf[0] == '1') { checkJni = true; } } property_get("dalvik.vm.execution-mode", propBuf, ""); if (strcmp(propBuf, "int:portable") == 0) { executionMode = KEMIntPortable; } else if (strcmp(propBuf, "int:fast") == 0) { executionMode = KEMIntFast; } else if (strcmp(propBuf, "int:jit") == 0) { executionMode = KEMJitCompiler; } // ... 省略大部分參數(shù)設(shè)置 /** * 設(shè)置虛擬機(jī)的heapsize,默認(rèn)為16m。絕大多數(shù)廠商都會(huì)在build.prop文件里修改這個(gè)屬性,一般是256m。 * heapsize不能設(shè)置得過(guò)小,否則在操作大尺寸的圖片時(shí)無(wú)法分配所需的內(nèi)存。 */ strcpy(heapsizeOptsBuf, "-Xmx"); property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m"); opt.optionString = heapsizeOptsBuf; mOptions.add(opt); // ...... if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) { ALOGE("JNI_CreateJavaVM failed\n"); goto bail; } result = 0; bail: free(stackTraceFile); return result; }
更多虛擬機(jī)參數(shù)的設(shè)置,我這里就不做特殊說(shuō)明了,大家感興趣可以自行g(shù)oogle。(ps:因?yàn)槲也惶摂M機(jī)這一塊…)
注冊(cè)JNI函數(shù)——startReg
上面講了如何創(chuàng)建虛擬機(jī),接下來(lái)需要給這個(gè)虛擬機(jī)注冊(cè)一些JNI函數(shù)。正是因?yàn)楹罄m(xù)的Java世界用到的一些函數(shù)是采用native方式實(shí)現(xiàn)的,所以才必須提前注冊(cè)這些函數(shù)。
接下來(lái),我們來(lái)看一下startReg函數(shù)的源碼實(shí)現(xiàn):
int AndroidRuntime::startReg(JNIEnv* env) { // 設(shè)置Thread類的線程創(chuàng)建函數(shù)為javaCreateThreadEtc androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc); ALOGV("--- registering native functions ---\n"); env->PushLocalFrame(200); if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) { env->PopLocalFrame(NULL); return -1; } env->PopLocalFrame(NULL); return 0; }
關(guān)鍵是需要注冊(cè)JNI函數(shù),具體實(shí)現(xiàn)是由register_jni_procs函數(shù)實(shí)現(xiàn)的,我們來(lái)看一下這個(gè)函數(shù)的具體實(shí)現(xiàn)(/frameworks/base/core/jni/AndroidRuntime.cpp):
static int register_jni_procs(const RegJNIRec array[], size_T count, JNIEnv* env) { for (size_t i = 0; i < count; i ++) { if (array[i].mProc(env) < 0) { #ifndef NDEBUG ALOGD("------!!! %s failed to load\n", array[i].mName); #endif return -1; } } return 0; }
通過(guò)源碼,我們可以看到,register_jni_procs只是對(duì)array數(shù)組的mProc函數(shù)的封裝,而array數(shù)組指向的是gRegJNI數(shù)組,我們來(lái)看一下這個(gè)數(shù)組的實(shí)現(xiàn):
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_EventLog), REG_JNI(register_android_util_Log), REG_JNI(register_android_util_FloatMath), REG_JNI(register_android_text_format_Time), REG_JNI(register_android_content_AssetManager), REG_JNI(register_android_content_StringBlock), REG_JNI(register_android_content_XmlBlock), REG_JNI(register_android_emoji_EmojiFactory), REG_JNI(register_android_text_AndroidCharacter), REG_JNI(register_android_text_AndroidBidi), REG_JNI(register_android_view_InputDevice), REG_JNI(register_android_view_KeyCharacterMap), REG_JNI(register_android_os_Process), REG_JNI(register_android_os_SystemProperties), REG_JNI(register_android_os_Binder), REG_JNI(register_android_os_Parcel), REG_JNI(register_android_view_DisplayEventReceiver), REG_JNI(register_android_nio_utils), REG_JNI(register_android_graphics_Graphics), REG_JNI(register_android_view_GraphicBuffer), REG_JNI(register_android_view_GLES20DisplayList), REG_JNI(register_android_view_GLES20Canvas), REG_JNI(register_android_view_HardwareRenderer), REG_JNI(register_android_view_Surface), REG_JNI(register_android_view_SurfaceControl), REG_JNI(register_android_view_SurfaceSession), REG_JNI(register_android_view_TextureView), REG_JNI(register_com_google_android_gles_jni_EGLImpl), REG_JNI(register_com_google_android_gles_jni_GLImpl), REG_JNI(register_android_opengl_jni_EGL14), REG_JNI(register_android_opengl_jni_EGLExt), REG_JNI(register_android_opengl_jni_GLES10), REG_JNI(register_android_opengl_jni_GLES10Ext), REG_JNI(register_android_opengl_jni_GLES11), REG_JNI(register_android_opengl_jni_GLES11Ext), REG_JNI(register_android_opengl_jni_GLES20), REG_JNI(register_android_opengl_jni_GLES30), REG_JNI(register_android_graphics_Bitmap), REG_JNI(register_android_graphics_BitmapFactory), REG_JNI(register_android_graphics_BitmapRegionDecoder), REG_JNI(register_android_graphics_Camera), REG_JNI(register_android_graphics_CreateJavaOutputStreamAdaptor), REG_JNI(register_android_graphics_Canvas), REG_JNI(register_android_graphics_ColorFilter), REG_JNI(register_android_graphics_DrawFilter), REG_JNI(register_android_graphics_Interpolator), REG_JNI(register_android_graphics_LayerRasterizer), REG_JNI(register_android_graphics_MaskFilter), REG_JNI(register_android_graphics_Matrix), REG_JNI(register_android_graphics_Movie), REG_JNI(register_android_graphics_NinePatch), REG_JNI(register_android_graphics_Paint), REG_JNI(register_android_graphics_Path), REG_JNI(register_android_graphics_PathMeasure), REG_JNI(register_android_graphics_PathEffect), REG_JNI(register_android_graphics_Picture), REG_JNI(register_android_graphics_PorterDuff), REG_JNI(register_android_graphics_Rasterizer), REG_JNI(register_android_graphics_Region), REG_JNI(register_android_graphics_Shader), REG_JNI(register_android_graphics_SurfaceTexture), REG_JNI(register_android_graphics_Typeface), REG_JNI(register_android_graphics_Xfermode), REG_JNI(register_android_graphics_YuvImage), REG_JNI(register_android_graphics_pdf_PdfDocument), REG_JNI(register_android_database_CursorWindow), REG_JNI(register_android_database_SQLiteConnection), REG_JNI(register_android_database_SQLiteGlobal), REG_JNI(register_android_database_SQLiteDebug), REG_JNI(register_android_os_Debug), REG_JNI(register_android_os_FileObserver), REG_JNI(register_android_os_MessageQueue), REG_JNI(register_android_os_SELinux), REG_JNI(register_android_os_Trace), REG_JNI(register_android_os_UEventObserver), REG_JNI(register_android_net_LocalSocketImpl), REG_JNI(register_android_net_NetworkUtils), REG_JNI(register_android_net_TrafficStats), REG_JNI(register_android_net_wifi_WifiNative), REG_JNI(register_android_os_MemoryFile), REG_JNI(register_com_android_internal_os_ZygoteInit), REG_JNI(register_android_hardware_Camera), REG_JNI(register_android_hardware_camera2_CameraMetadata), REG_JNI(register_android_hardware_SensorManager), REG_JNI(register_android_hardware_SerialPort), REG_JNI(register_android_hardware_UsbDevice), REG_JNI(register_android_hardware_UsbDeviceConnection), REG_JNI(register_android_hardware_UsbRequest), REG_JNI(register_android_media_AudioRecord), REG_JNI(register_android_media_AudioSystem), REG_JNI(register_android_media_AudioTrack), REG_JNI(register_android_media_JetPlayer), REG_JNI(register_android_media_RemoteDisplay), REG_JNI(register_android_media_ToneGenerator), REG_JNI(register_android_opengl_classes), REG_JNI(register_android_server_NetworkManagementSocketTagger), REG_JNI(register_android_server_Watchdog), REG_JNI(register_android_ddm_DdmHandleNativeHeap), REG_JNI(register_android_backup_BackupDataInput), REG_JNI(register_android_backup_BackupDataOutput), REG_JNI(register_android_backup_FileBackupHelperBase), REG_JNI(register_android_backup_BackupHelperDispatcher), REG_JNI(register_android_app_backup_FullBackup), REG_JNI(register_android_app_ActivityThread), REG_JNI(register_android_app_NativeActivity), REG_JNI(register_android_view_InputChannel), REG_JNI(register_android_view_InputEventReceiver), REG_JNI(register_android_view_InputEventSender), REG_JNI(register_android_view_InputQueue), REG_JNI(register_android_view_KeyEvent), REG_JNI(register_android_view_MotionEvent), REG_JNI(register_android_view_PointerIcon), REG_JNI(register_android_view_VelocityTracker), REG_JNI(register_android_content_res_ObbScanner), REG_JNI(register_android_content_res_Configuration), REG_JNI(register_android_animation_PropertyValuesHolder), REG_JNI(register_com_android_internal_content_NativeLibraryHelper), REG_JNI(register_com_android_internal_net_NetworkStatsFactory), }; #ifdef NDEBUG #define REG_JNI(name) {name} struct RegJNIRec { int (*mProc)(JNIEnv*); }; #else #define REG_JNI(name) {name, #name} struct RegJNIRec { int (*mProc)(JNIEnv*); const char* mName; }; #endif
可以看到,REG_JNI是一個(gè)宏,宏里面包括的就是那個(gè)參數(shù)為JNIEnv*,返回值為int的函數(shù)指針mProc,我們以register_android_debug_JNITest為例,源碼位置為/frameworks/base/core/jni/android_debug_JNITest.cpp:
#define NELEM(x) (sizeof(x)/sizeof(*(x))) int register_android_debug_JNITest(JNIEnv* env) { return jniRegisterNativeMethods(env, "android/debug/JNITest", gMethods, NELEM(gMethods)); }
可以看到,mProc其實(shí)就是為Java類注冊(cè)JNI函數(shù)。
進(jìn)入JAVA世界
可以看到CallStaticVoidMethod最終將調(diào)用com.android.internal.os.ZygoteInit的main函數(shù),下面就來(lái)看一下這個(gè)Java世界的入口函數(shù)。源碼位置:/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java,源碼如下:
public static void main(String argv[]) { try { SamplingProfilerIntegration.start(); // 1. 注冊(cè)zygote用的socket registerZygoteSocket(); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis()); // 2. 預(yù)加載類和資源 preload(); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis()); SamplingProfilerIntegration.writeZygoteSnapshot(); // 強(qiáng)制執(zhí)行一次垃圾收集 gc(); Trace.setTracingEnabled(false); if (argv.length != 2) { throw new RuntimeException(argv[0] + USAGE_STRING); } if (argv[1].equals("start-system-server")) { // 3. 啟動(dòng)system-server startSystemServer(); } else if (!argv[1].equals("")) { throw new RuntimeException(argv[0] + USAGE_STRING); } Log.i(TAG, "Accepting command socket connections"); // 4. 進(jìn)入請(qǐng)求應(yīng)答模式 runSelectLoop(); closeServerSocket(); } catch(MethodAndArgsCaller caller) { caller.run(); } catch(RuntimeException ex) { Log.e(TAG, "Zygote died with exception", ex); closeServerSocket(); throw ex; } }
上述代碼中有5個(gè)重要的點(diǎn),我已經(jīng)通過(guò)標(biāo)號(hào)標(biāo)記出來(lái)了,接下來(lái)我們分別分析一下這5點(diǎn)函數(shù)的具體實(shí)現(xiàn)。
建立IPC通信服務(wù)端——registerZygoteSocket
zygote及系統(tǒng)中其他程序的通信沒有使用Binder,而是采用了基于AF_UNIX類型的socket。registerZygoteSocket函數(shù)的使命正是建立這個(gè)Socket,實(shí)現(xiàn)代碼如下:
private static void registerZygoteSocket() { if (sServerSocket == null) { int fileDesc; try { String env = System.getenv(ANDROID_SOCKET_ENV); fileDesc = Integer.parseInt(env); } catch (RuntimeException ex) { throw new RuntimeException(ANDROID_SOCKET_ENV + " unset or invalid", ex); } try { sServerSocket = new LocalServerSocket(createFileDescriptor(fileDesc)); } catch(IOException ex) { throw new RuntimeException("Error binding to local socket '" + fileDesc + "'", ex); } } } public class LocalServerSocket { private final LocalSocketImpl impl; private final LocalSocketAddress localAddress; private static final int LISTEN_BACKLOG = 50; /** * Create a LocalServerSocket from a file descriptor that's already * been created and bound. listen() will be called immediately on it. * Used for cases where file descriptors are passed in via environment * variables. */ public LocalServerSocket(FileDescriptor fd) throws IOException { impl = new LocalSocketImpl(fd); impl.listen(LISTEN_BACKLOG); localAddress = impl.getSockAddress(); } }
registerZygoteSocket很簡(jiǎn)單,就是創(chuàng)建一個(gè)服務(wù)端的socket。
預(yù)加載類和資源——preload
我們先來(lái)看一下preload函數(shù)實(shí)現(xiàn):
static void preload() { preloadClasses(); preloadResources(); preloadOpenGL(); }
preload函數(shù)里面分別調(diào)用了三個(gè)預(yù)加載函數(shù),我們分別來(lái)分析一下這幾個(gè)函數(shù)的實(shí)現(xiàn)。
首先是preloadClasses,函數(shù)實(shí)現(xiàn)如下:
private static final int UNPRIVILEGED_UID = 9999; private static final int UNPRIVILEGED_GID = 9999; private static final int ROOT_UID = 0; private static final int ROOT_GID = 0; private static void preloadClasses() { final VMRuntime runtime = VMRuntime.getRuntime(); InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream(PRELOADED_CLASSES); if (is == null) { Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + "."); } else { Log.i(TAG, "Preloading classes..."); long startTime = SystemClock.uptimeMillis(); setEffectiveGroup(UNPRIVILEGED_GID); setEffectiveGroup(UNPRIVILEGED_UID); float defaultUtilization = runtime.getTargetHeapUtilization(); runtime.setTargetHeapUtilization(0.8f); System.gc(); runtime.runFinalizationSync(); Debug.startAllocCounting(); try { // 創(chuàng)建一個(gè)緩沖區(qū)為256字符的輸入流 BufferedReader br = new BufferdReader(new InputStreamReader(is), 256); int count = 0; String line; while ((line = br.readLine()) != null) { // skip comments and blank lines. line = line.trim(); if (line.startsWith("#") || line.equals("")) { continue; } try { if (false) { Log.v(TAG, "Preloading " + line + "..."); } Class.forName(line); count ++; } catch (ClassNotFoundException e) { Log.w(TAG, "Class not found for preloading: " + line); } catch (UnsatisfiedLinkError e) { Log.w(TAG, "Problem preloading " + line + ": " + e); } catch(Throwable t) { Log.e(TAG, "Error preloading " + line + ".", t); } } Log.i(TAG, "...preloaded " + count + " classes in " + (SystemClock.uptimeMillis()-startTime) + "ms."); } catch (IOException e) { Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e); } finally { IoUtils.closeQuietly(is); runtime.setTargetHeapUtilization(defaultUtilization); runtime.preloadDexCaches(); Debug.stopAllocCounting(); setEffectiveUser(ROOT_UID); setEffectiveGroup(ROOT_GID); } } }
preloadClasses看起來(lái)很簡(jiǎn)單,但是實(shí)際上它有很多的類需要加載。可以查看一下/frameworks/base/preloaded-classes文件,這里面都是需要預(yù)加載的類。
接下來(lái),分析一下preloadResources函數(shù)的源碼:
private static final boolean PRELOAD_RESOURCES = true; private static void preloadResources() { final VMRuntime runtime = VMRuntime.getRuntime(); Debug.startAllocCounting(); try { System.gc(); runtime.runFinalizationSync(); mResources = Resources.getSystem(); mResources.startPreloading(); if (PRELOAD_RESOURCES) { Log.i(TAG, "Preloading resources..."); long startTime = SystemClock.uptimeMillis(); TypedArray ar = mResources.obtainTypedArray(com.android.internal.R.array.preloaded_drawables); int N = preloadDrawables(runtime, ar); ar.recycle(); Log.i(TAG, "...preloaded " + N + " resources in " + (SystemClock.uptimeMillis()-startTime) + "ms."); startTime = SystemClock.uptimeMillis(); ar = mResources.obtainTypedArray(com.android.internal.R.array.preloaded_color_state_lists); N = preloadColorstateLists(runtime, ar); ar.recycle(); Log.i(TAG, "...preloaded " + N + " resources in " + (SystemClock.uptimeMillis() - startTime) + "ms."); } mResources.finishPreloading(); } catch (RuntimeException e) { Log.w(TAG, "Failure preloading resources", e); } finally { Debug.stopAllocCounting(); } }
接下來(lái),是預(yù)加載OpenGL。源碼如下:
private static void preloadOpenGL() { if (!SystemProperties.getBoolean(PROPERTY_DISABLE_OPENGL_PRELOADING, false)) { EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY); } }
啟動(dòng)system_server
現(xiàn)在我們要分析第三個(gè)關(guān)鍵點(diǎn):startSystemServer。這個(gè)函數(shù)會(huì)創(chuàng)建java世界中系統(tǒng)Service所駐留的進(jìn)程system_server,該進(jìn)程是framework的核心。如何system_server掛掉,會(huì)導(dǎo)致zygote自殺。我們來(lái)看一下startSystemServer()實(shí)現(xiàn)源碼。
/** * Prepare the arguments and fork for the system server process. */ private static boolean startSystemServer() throws MethodAndArgsCaller, RuntimeException { long capabilities = posixCapabilitiesAsBits( OsConstants.CAP_KILL, OsConstants.CAP_NET_ADMIN, OsConstants.CAP_NET_BIND_SERVICE, OsConstants.CAP_NET_BROADCAST, OsConstants.CAP_NET_RAW, OsConstants.CAP_SYS_MODULE, OsConstants.CAP_SYS_NICE, OsConstants.CAP_SYS_RESOURCE, OsConstants.CAP_SYS_TIME, OsConstants.CAP_SYS_TTY_CONFIG ); // 設(shè)置參數(shù) String args[] = { "--setuid=1000", "--setgid=1000", "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007", "--capabilities=" + capabilities + "," + capabilities, "--runtime-init", "--nice-name=system_server", // 進(jìn)程名為system_server "com.android.server.SystemServer", }; ZygoteConnection.Arguments parsedArgs = null; int pid; try { parsedArgs = new ZygoteConnection.Arguments(args); ZygoteConnection.applyDebuggerSystemProperty(parsedArgs); ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs); /* Request to fork the system server process */ pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities ); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } /* For child process */ if (pid == 0) { handleSystemServerProcess(parsedArgs); } return true; }
有求必應(yīng)之等待請(qǐng)求——runSelectLoop
zygote從startSystemServer返回后,將進(jìn)入第四個(gè)關(guān)鍵的函數(shù):runSelectLoop。我們來(lái)看一下這個(gè)函數(shù)的實(shí)現(xiàn):
static final int GC_LOOP_COUNT = 10; private static void runSelectLoop() throws MethodAndArgsCaller { ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>(); ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>(); FileDescriptor[] fdArray = new FileDescriptor[4]; fds.add(sServerSocket.getFileDescriptor()); peers.add(null); int loopCount = GC_LOOP_COUNT; while (true) { int index; if (loopCount <= 0) { gc(); loopCount = GC_LOOP_COUNT; } else { loopCount --; } try { fdArray = fds.toArray(fdArray); index = selectReadable(fdArray); } catch(IOException ex) { throw new RuntimeException("Error in select()", ex); } if (index < 0) { throw new RuntimeException("Error in select()"); } else if (index == 0) { ZygoteConnection newPeer = acceptCommandPeer(); peers.add(newPeer); } } }
相關(guān)文章
c++ dynamic_cast與static_cast使用方法示例
本文用示例講解了dynamic_cast、static_cast子類與基類之間轉(zhuǎn)換功能的使用方法2013-11-11C++二維數(shù)組中數(shù)組元素存儲(chǔ)地址的計(jì)算疑問講解
今天小編就為大家分享一篇關(guān)于C++二維數(shù)組中數(shù)組元素存儲(chǔ)地址的計(jì)算疑問講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-02-02一文詳解C++子類函數(shù)為什么不能重載父類函數(shù)
這篇文章主要介紹了一文詳解C++子類函數(shù)為什么不能重載父類函數(shù),文章圍繞主題展開詳細(xì)的內(nèi)容戒殺,具有一定的參考價(jià)值,需要的朋友可以參考一下2022-09-09C++使用fdk-aac實(shí)現(xiàn)將音頻PCM編碼成aac
mp4的音頻流通常是aac編碼,我們做音視頻采集的時(shí)候就需要將,采集的音頻PCM編碼成aac,本文就來(lái)為大家介紹一下C++如何使用fdk-aac實(shí)現(xiàn)將音頻PCM編碼成aac吧2023-11-11