概要
从字面上看,zygote是“受精卵”的意思。zygote是android系统应用中一个相当重要的进程,它的主要功能是执行android应用程序。在android系统中运行新的应用,如同受精分裂一样,需要跟zygote进程(拥有应用程序运行时所需要的各种元素与条件)结合后才能执行。
zygote进程运行时,会初始化Dalvik虚拟机,并启动它。android的应用程序是由Java编写的,它们不能直接以本地进程的形态运行在Linux上,只能运行在Dalvik虚拟机中。并且,每个应用程序都运行在各自的虚拟机中,应用程序每次运行都要重新初始化并启动虚拟机,这个过程会耗费相当长时间,是拖慢应用程序的原因之一。因此,在android中,应用程序运行前,zygote进程通过共享已运行的虚拟机的代码和内存信息,缩短应用程序运行所耗费的时间。并且,它会事先将应用程序要使用的android framework中的类和资源加载到内存中,并组织所使用资源的链接信息,这就会节省大量时间,提高程序运行速度。
在android系统中有以下两种进程:
- Java应用程序,主要基于ART虚拟机,所有的应用程序apk都属于这类。
- native程序,也就是使用C和C++语言开发的 程序,比如bootanimation。
所有的Java应用程序进程以及系统服务SystemServer进程都是由zygote进程通过Linux的fork()函数孵化出来,而native进程则由init进程创建启动。zygote进程最初的名字是app_process,但是zygote进程在启动的过程中,通过Linux下的pctrl系统调用换成了zygote。
zygote是一个C/S模型,zygote进程作为服务端,其他进程作为一个客户端向它发出“孵化”请求,而zygote接收这个请求之后就会“孵化”出一个新的进程。如下图,当Launcher里的应用程序图标去启动一个新的应用程序进程时,这个请求会到达框架层的核心服务ActivityManagerService中,当ActivityManagerService收到这个请求之后,会通过调用Process类发送一个“孵化”子进程的Socket请求,而zygote监听到了这个请求之后就会立刻fork一个新的进程出来。
zygote进程的启动
zygote本身是一个native的应用程序,它被init进程启动起来,在init.rc文件中的配置如下:
service zygote /system/bin/app_process64 -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
第一行代码的意思是,这个native service的名字为zygote,它的可执行程序是 /system/bin/app_process64。
第二行的关键字class为main,表示service的类型是main。
第三行的关键字socket,表示zygote进程会创建一个名称为zygote的socket,通过adb可以在/dev/socket目录下看到这个名为zygote的文件。这里定义的socket的类型是UNIX domain Socket,用作进程间通信,当启动一个新的应用程序时,系统框架中服务ActivityManagerService会调用Process类,Process类通过这个socket来和zygote进程通信,请求zygote进程fork一个应用程序。
最后几行关键字onrestart,表示这个zygote进程重启时需要执行的命令。
zygote进程对应的主文件为app_main.cpp,当它被init进程启动起来之后,就会进入主文件app_main.cpp的main()函数。
int main(int argc, char* const argv[])
{12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {if (errno != EINVAL) {LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno));return 12;}}AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));argc--;argv++;int i;for (i = 0; i < argc; i++) {if (argv[i][0] != '-') {break;}if (argv[i][1] == '-' && argv[i][2] == 0) {++i; // Skip --.break;}runtime.addOption(strdup(argv[i]));}bool zygote = false;bool startSystemServer = false;bool application = false;String8 niceName;String8 className;++i;while (i < argc) {const char* arg = argv[i++];if (strcmp(arg, "--zygote") == 0) {zygote = true;niceName = ZYGOTE_NICE_NAME; // ZYGOTE_NICE_NAME就是“zygote”,此处已换名字} else if (strcmp(arg, "--start-system-server") == 0) {startSystemServer = true; // 在init.rc里配置了前面这些参数,而zygote进程在启动的时候,init进程会传过来这些参数,所以此处把startSystemServer设置为true,代表SystemServer。} 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;}}Vector<String8> args;if (!className.isEmpty()) {args.add(application ? String8("application") : String8("tool"));runtime.setClassNameAndArgs(className, argc - i, argv + i);} else {maybeCreateDalvikCache();if (startSystemServer) {args.add(String8("start-system-server"));}char prop[PROP_VALUE_MAX];if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",ABI_LIST_PROPERTY);return 11;}String8 abiFlag("--abi-list=");abiFlag.append(prop);args.add(abiFlag);for (; i < argc; ++i) {args.add(String8(argv[i]));}}if (!niceName.isEmpty()) {runtime.setArgv0(niceName.string());// 此处调用set_process_name()函数,通过Linux下的pctrl系统调用把名字“app_process”换成了“zygote”set_process_name(niceName.string());}if (zygote) {// zygote为true代表的是zygote进程,也就是谁现在正在启动zygote进程。因为zygote进程是通过自己的资源复制一份来fork一个新的子进程的,也就是说子进程也会进入这个文件的main函数,所以通过这个zygote变量就可以来区分runtime.start("com.android.internal.os.ZygoteInit", args, zygote);} else if (className) {runtime.start("com.android.internal.os.RuntimeInit", args, zygote);} 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;}}
可以看到main()函数最后会调用runtime的start()函数,runtime是一个AppRuntime对象,AppRuntime类继承AndroidRuntime的start()函数。
void AndroidRuntime::start(const char* className, const Vector
& options, bool zygote)
{1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980ALOGD(">>>>>> START %s uid %d <<<<<<\n",className != NULL ? className : "(unknown)", getuid());static const String8 startSystemServer("start-system-server");for (size_t i = 0; i < options.size(); ++i) {if (options[i] == startSystemServer) {const int LOG_BOOT_PROGRESS_START = 3000;LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));}}const char* rootDir = getenv("ANDROID_ROOT");if (rootDir == NULL) {rootDir = "/system";if (!hasDir("/system")) {LOG_FATAL("No root directory specified, and /android does not exist.");return;}setenv("ANDROID_ROOT", rootDir, 1);}JniInvocation jni_invocation;jni_invocation.Init(NULL);JNIEnv* env;// 启动虚拟机if (startVm(&mJavaVM, &env, zygote) != 0) {return;}onVmCreated(env);// 注册JNI函数if (startReg(env) < 0) {ALOGE("Unable to register all android natives\n");return;}jclass stringClass;jobjectArray strArray;jstring classNameStr;stringClass = env->FindClass("java/lang/String");assert(stringClass != NULL);strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);assert(strArray != NULL);classNameStr = env->NewStringUTF(className);assert(classNameStr != NULL);env->SetObjectArrayElement(strArray, 0, classNameStr);for (size_t i = 0; i < options.size(); ++i) {jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());assert(optionsStr != NULL);env->SetObjectArrayElement(strArray, i + 1, optionsStr);}char* slashClassName = toSlashClassName(className);jclass startClass = env->FindClass(slashClassName);if (startClass == NULL) {ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);} else {// 调用类的main方法jmethodID startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");if (startMeth == NULL) {ALOGE("JavaVM unable to find main() in '%s'\n", className);} else {// 调用ZygoteInit的main函数env->CallStaticVoidMethod(startClass, startMeth, strArray);if (env->ExceptionCheck())threadExitUncaughtException(env);}}free(slashClassName);ALOGD("Shutting down VM\n");if (mJavaVM->DetachCurrentThread() != JNI_OK)ALOGW("Warning: unable to detach main thread\n");if (mJavaVM->DestroyJavaVM() != 0)ALOGW("Warning: VM did not shut down cleanly\n");}
可以看到,AndroidRuntime的start()函数主要做了以下三件事情。
调用startVM()函数启动虚拟机
int AndroidRuntime::startVm(JavaVM pJavaVM, JNIEnv pEnv, bool zygote){
1234567.......// 主要通过JNI_CreateJavaVM()创建虚拟机if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {ALOGE("JNI_CreateJavaVM failed\n");return -1;}return 0;}
调用startReg()函数注册JNI方法
int AndroidRuntime::startReg(JNIEnv* env){
123456789101112ATRACE_NAME("RegisterAndroidNatives");androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);ALOGV("--- registering native functions ---\n");env->PushLocalFrame(200);// startReg()函数通过register_jni_procs()函数去进一步注册,并且传递的值是gRegJNI变量,gRegJNI是一个数组。在android中,Java世界要调用native世界的函数就要用JNI机制,并且android系统中也大量使用JNI机制,register_jni_procs通过这个数组来完成Java到native方法的映射。if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {env->PopLocalFrame(NULL);return -1;}env->PopLocalFrame(NULL);return 0;}
调用ZygoteInit类的main函数
public static void main(String argv[]){
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465ZygoteHooks.startZygoteNoThreadCreation();try {Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygoteInit");RuntimeInit.enableDdms();SamplingProfilerIntegration.start();boolean startSystemServer = false;String socketName = "zygote";String abiList = null;for (int i = 1; i < argv.length; i++) {if ("start-system-server".equals(argv[i])) {startSystemServer = true;} else if (argv[i].startsWith(ABI_LIST_ARG)) {abiList = argv[i].substring(ABI_LIST_ARG.length());} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {socketName = argv[i].substring(SOCKET_NAME_ARG.length());} else {throw new RuntimeException("Unknown command line argument: " + argv[i]);}}if (abiList == null) {throw new RuntimeException("No ABI list supplied.");}registerZygoteSocket(socketName);Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygotePreload");EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,SystemClock.uptimeMillis());preload();EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,SystemClock.uptimeMillis());Trace.traceEnd(Trace.TRACE_TAG_DALVIK);SamplingProfilerIntegration.writeZygoteSnapshot();Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PostZygoteInitGC");gcAndFinalize();Trace.traceEnd(Trace.TRACE_TAG_DALVIK);Trace.traceEnd(Trace.TRACE_TAG_DALVIK);Trace.setTracingEnabled(false);Zygote.nativeUnmountStorageOnInit();ZygoteHooks.stopZygoteNoThreadCreation();if (startSystemServer) {startSystemServer(abiList, socketName);}Log.i(TAG, "Accepting command socket connections");runSelectLoop(abiList);closeServerSocket();} catch (MethodAndArgsCaller caller) {caller.run();} catch (RuntimeException ex) {Log.e(TAG, "Zygote died with exception", ex);closeServerSocket();throw ex;}}
ZygoteInit类的main()方法主要做了以下5项工作:
调用registerZygoteSocket()函数创建一个zygote的socket接口,用来和AMS通信
private static void registerZygoteSocket(String socketName) {
1234567891011121314151617181920if (sServerSocket == null) {// 使用文件描述符作为参数,通过new关键字创建了一个Java层的LocalServerSocket对象,目的是等待创建新的应用程序进程请求连接,而这个文件描述符代表的就是前面说的/dev/socket/zygote,即在init.rc中zygote service配置的内容int fileDesc;final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;try {String env = System.getenv(fullSocketName);fileDesc = Integer.parseInt(env);} catch (RuntimeException ex) {throw new RuntimeException(fullSocketName + " unset or invalid", ex);}try {FileDescriptor fd = new FileDescriptor();fd.setInt$(fileDesc);sServerSocket = new LocalServerSocket(fd);} catch (IOException ex) {throw new RuntimeException("Error binding to local socket '" + fileDesc + "'", ex);}} }
调用preload()预加载类和资源
static void preload() {
123456789101112131415161718192021222324Log.d(TAG, "begin preload");Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "BeginIcuCachePinning");beginIcuCachePinning();Trace.traceEnd(Trace.TRACE_TAG_DALVIK);Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadClasses");// 加载类preloadClasses();Trace.traceEnd(Trace.TRACE_TAG_DALVIK);Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadResources");// 加载资源preloadResources();Trace.traceEnd(Trace.TRACE_TAG_DALVIK);Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadOpenGL");// 加载OpenGLpreloadOpenGL();Trace.traceEnd(Trace.TRACE_TAG_DALVIK);// 加载共享库(预加载"android","compiler_rt", "jnigraphics"这几个库);preloadSharedLibraries();preloadTextResources();WebViewFactory.prepareWebViewInZygote();endIcuCachePinning();warmUpJcaProviders();Log.d(TAG, "end preload");}
调用startSystemServer()函数来启动SystemServer进程
调用runSelectLoop()函数在前面创建的socket接口上进入一个无限循环,等待核心服务AMS请求创建新的应用程序进程
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
|
|
}
- 调用caller.run()方法,当启动一个新进程,会抛出MethodAndArgsCaller异常,当捕获了这个异常之后,就调用MethodAndArgsCaller类的run方法
综上可以通过一张图来小结一下zygote启动的大概过程
启动system_server进程
首先,回顾一下android framework的启动过程
zygote启动虚拟机后,会再生成一个虚拟机实例,以便运行名称为SystemServer的Java服务,SystemServer用于运行Audio Flinger与Surface Flinger本地服务。在运行完所需的本地服务后,SystemServer开始运行android framework的服务,如AMS、WMS、PMS等。
启动系统服务system_server进程从ZygoteInit.java的main()方法调用startSystemServer()方法开始。
|
|
接着看handleSystemServerProcess()方法实现
private static void handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
|
|
}
handleSystemServerProcess()函数在最后调用了RuntimeInit.zygoteInit()方法,zygoteInit()主要调用了nativeZygoteInit()和applicationInit()这两个方法。
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
|
|
}
nativeZygoteInit()是一个native的方法,对应于jni下的AndroidRuntime.cpp文件里的com_android_internal_os_RuntimeInit_nativeZygoteInit()函数。
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz) {
|
|
}
visual void onZygoteInit() {
|
|
}
回到前面再继续看看applicationInit()方法怎样一步步进入SystemServer的main()方法。
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
|
|
}
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
|
|
}
启动app应用程序进程
前面分析了zygote如何启动SystemServer子进程,接下类再分析zygote如何启动其他子进程,也就是创建应用程序进程的过程,这个过程和创建SystemServer进程基本一样。
当点击Launcher主界面的一个应用程序图标时,如果这个应用程序还未曾启动,就会启动它。而判断应用程序有没有启动都由核心服务ActivityManagerService来做,它的startProcessLocked()方法会真正地启动应用程序子进程。
private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186long startTime = SystemClock.elapsedRealtime();if (app.pid > 0 && app.pid != MY_PID) {checkTime(startTime, "startProcess: removing from pids map");synchronized (mPidsSelfLocked) {mPidsSelfLocked.remove(app.pid);mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);}checkTime(startTime, "startProcess: done removing from pids map");app.setPid(0);}if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,"startProcessLocked removing on hold: " + app);mProcessesOnHold.remove(app);checkTime(startTime, "startProcess: starting to update cpu stats");updateCpuStats();checkTime(startTime, "startProcess: done updating cpu stats");try {try {final int userId = UserHandle.getUserId(app.uid);AppGlobals.getPackageManager().checkPackageStartable(app.info.packageName, userId);} catch (RemoteException e) {throw e.rethrowAsRuntimeException();}int uid = app.uid;int[] gids = null;int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;if (!app.isolated) {int[] permGids = null;try {checkTime(startTime, "startProcess: getting gids from package manager");final IPackageManager pm = AppGlobals.getPackageManager();permGids = pm.getPackageGids(app.info.packageName,MATCH_DEBUG_TRIAGED_MISSING, app.userId);MountServiceInternal mountServiceInternal = LocalServices.getService(MountServiceInternal.class);mountExternal = mountServiceInternal.getExternalStorageMountMode(uid,app.info.packageName);} catch (RemoteException e) {throw e.rethrowAsRuntimeException();}if (ArrayUtils.isEmpty(permGids)) {gids = new int[2];} else {gids = new int[permGids.length + 2];System.arraycopy(permGids, 0, gids, 2, permGids.length);}gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));gids[1] = UserHandle.getUserGid(UserHandle.getUserId(uid));}checkTime(startTime, "startProcess: building args");if (mFactoryTest != FactoryTest.FACTORY_TEST_OFF) {if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL&& mTopComponent != null&& app.processName.equals(mTopComponent.getPackageName())) {uid = 0;}if (mFactoryTest == FactoryTest.FACTORY_TEST_HIGH_LEVEL&& (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {uid = 0;}}int debugFlags = 0;if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;}if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||mSafeMode == true) {debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;}if ("1".equals(SystemProperties.get("debug.checkjni"))) {debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;}String genDebugInfoProperty = SystemProperties.get("debug.generate-debug-info");if ("true".equals(genDebugInfoProperty)) {debugFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO;}if ("1".equals(SystemProperties.get("debug.jni.logging"))) {debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;}if ("1".equals(SystemProperties.get("debug.assert"))) {debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;}if (mNativeDebuggingApp != null && mNativeDebuggingApp.equals(app.processName)) {debugFlags |= Zygote.DEBUG_ALWAYS_JIT; // Don't interpret anythingdebugFlags |= Zygote.DEBUG_GENERATE_DEBUG_INFO; // Generate debug infodebugFlags |= Zygote.DEBUG_NATIVE_DEBUGGABLE; // Disbale optimizationsmNativeDebuggingApp = null;}String requiredAbi = (abiOverride != null) ? abiOverride : app.info.primaryCpuAbi;if (requiredAbi == null) {requiredAbi = Build.SUPPORTED_ABIS[0];}String instructionSet = null;if (app.info.primaryCpuAbi != null) {instructionSet = VMRuntime.getInstructionSet(app.info.primaryCpuAbi);}app.gids = gids;app.requiredAbi = requiredAbi;app.instructionSet = instructionSet;boolean isActivityProcess = (entryPoint == null);if (entryPoint == null) entryPoint = "android.app.ActivityThread";Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +app.processName);checkTime(startTime, "startProcess: asking zygote to start proc");// AMS的startProcessLocked()方法调用了Process类的start()方法为应用程序创建新的进程,这里的参数entryPoint为"android.app.ActivityThread",它是传进去的第一个参数,也就是应用程序初始化进程时要加载的主文件Java类。当应用程序启动之后,会把这个类加载到进程,调用它的main()方法作为应用程序进程的入口。Process.ProcessStartResult startResult = Process.start(entryPoint,app.processName, uid, uid, gids, debugFlags, mountExternal,app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,app.info.dataDir, entryPointArgs);checkTime(startTime, "startProcess: returned from zygote!");Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);if (app.isolated) {mBatteryStatsService.addIsolatedUid(app.uid, app.info.uid);}mBatteryStatsService.noteProcessStart(app.processName, app.info.uid);checkTime(startTime, "startProcess: done updating battery stats");EventLog.writeEvent(EventLogTags.AM_PROC_START,UserHandle.getUserId(uid), startResult.pid, uid,app.processName, hostingType,hostingNameStr != null ? hostingNameStr : "");try {AppGlobals.getPackageManager().logAppProcessStartIfNeeded(app.processName, app.uid,app.info.seinfo, app.info.sourceDir, startResult.pid);} catch (RemoteException ex) {}if (app.persistent) {Watchdog.getInstance().processStarted(app.processName, startResult.pid);}checkTime(startTime, "startProcess: building log message");StringBuilder buf = mStringBuilder;buf.setLength(0);buf.append("Start proc ");buf.append(startResult.pid);buf.append(':');buf.append(app.processName);buf.append('/');UserHandle.formatUid(buf, uid);if (!isActivityProcess) {buf.append(" [");buf.append(entryPoint);buf.append("]");}buf.append(" for ");buf.append(hostingType);if (hostingNameStr != null) {buf.append(" ");buf.append(hostingNameStr);}Slog.i(TAG, buf.toString());app.setPid(startResult.pid);app.usingWrapper = startResult.usingWrapper;app.removed = false;app.killed = false;app.killedByAm = false;checkTime(startTime, "startProcess: starting to update pids map");synchronized (mPidsSelfLocked) {this.mPidsSelfLocked.put(startResult.pid, app);if (isActivityProcess) {Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);msg.obj = app;mHandler.sendMessageDelayed(msg, startResult.usingWrapper? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);}}checkTime(startTime, "startProcess: done updating pids map");} catch (RuntimeException e) {Slog.e(TAG, "Failure starting process " + app.processName, e);forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid), false,false, true, false, false, UserHandle.getUserId(app.userId), "start failure");}}
接下来看看Process的start()方法。
public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String[] zygoteArgs) {12345678910try {return startViaZygote(processClass, niceName, uid, gid, gids,debugFlags, mountExternal, targetSdkVersion, seInfo,abi, instructionSet, appDataDir, zygoteArgs);} catch (ZygoteStartFailedEx ex) {Log.e(LOG_TAG,"Starting VM process through Zygote failed");throw new RuntimeException("Starting VM process through Zygote failed", ex);}}
Process类的start()方法就是简单地调用startViaZygote()方法来进一步操作。
public static ProcessStartResult startViaZygote(final String processClass,
final String niceName,
final int uid, final int gid,
final int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String[] extraArgs)throws ZygoteStartFailedEx {
|
|
}
|
|
|
|
1234567891011121314151617181920212223242526272829303132333435363738
private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr) throws ZygoteInit.MethodAndArgsCaller { closeSocket(); ZygoteInit.closeServerSocket(); if (descriptors != null) { try { Os.dup2(descriptors[0], STDIN_FILENO); Os.dup2(descriptors[1], STDOUT_FILENO); Os.dup2(descriptors[2], STDERR_FILENO); for (FileDescriptor fd: descriptors) { IoUtils.closeQuietly(fd); } newStderr = System.err; } catch (ErrnoException ex) { Log.e(TAG, "Error reopening stdio", ex); } } if (parsedArgs.niceName != null) { Process.setArgV0(parsedArgs.niceName); } Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); if (parsedArgs.invokeWith != null) { WrapperInit.execApplication(parsedArgs.invokeWith, parsedArgs.niceName, parsedArgs.targetSdkVersion, VMRuntime.getCurrentInstructionSet(), pipeFd, parsedArgs.remainingArgs); } else { // handleChildProc()方法调用了RuntimeInit类的zygoteInit()方法来做进一步处理,后面的启动过程跟前面启动SystemServer的过程基本一样,唯一不同的是SystemServer进程启动之后进入的主类是SystemServer.java,而应用程序进程启动起来之后进入的主类是ActivityThread.java,但最终都会进入main()方法。 RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, null /* classLoader */); }}
小结
至此,zygote进程以及zygote进程启动SystemServer进程和启动应用程序进程就分析完了。zygote进程为了启动SystemServer进程和启动应用程序进程主要做了两件事:
- 初始化Binder驱动用来进行进程间通信
- 通过反射进入main()方法
zygote进程是android应用运行必须的进程,zygote进程如何运行、如何初始化,以及如何通过它来提高应用的运行速度等,是需要讨论的主要内容。在android平台下,zygote进程有助于快速运行应用程序,可以高效地向android平台添加资源,快速加载相关类,在运行新的应用程序的过程中减小系统开销。