从上一篇init的启动可以看到,zygote由init进程解析init.zygoteXXX.rc文件,然后fork进程,并为zygote进程创建了/dev/socket/zygote的socket接口,然后创建zygote进程,执行/system/bin/app_process,传入参数:-Xzygote /system/bin –zygote –start-system-server
本文,我们看下app_process干了些什么事情
仍然是AndroidStudio查找源码的流程:
- Ctrl + Shift + F 全局查找字符串 := app_process
- 找到Android.mk文件:frameworks/base/cmds/app_process/Android.mk
- 对应的LOCAL_SRC_FILES:= \app_main.cpp,因此app_process的源码位于frameworks/base/cmds/app_process/app_main.cpp中
开始阅读:app_main.cpp -> main()方法
记住,在init在执行的时候,入参是:-Xzygote /system/bin –zygote –start-system-server,解析得到的args = {“-Xzygote” “/system/bin”,”-zygote“, ”-start-system-server“},携带这些参数,我们来看下main方法的执行情况
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
| 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; break; } runtime.addOption(strdup(argv[i])); } ... ++i; while (i < argc) { const char* arg = argv[i++]; if (strcmp(arg, "--zygote") == 0) { zygote = true; niceName = ZYGOTE_NICE_NAME; } 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) == 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(niceName.string()); } if (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; }
|
AppRuntime->start()方法
AppRuntime的定义在app_main.cpp中,继承于AndroidRuntime类,类文件位于frameworks/base/core/jni/AndroidRuntime.cpp,头文件位于frameworks/base/include/android_runtime/AndroidRuntime.h
而AppRuntime主要重写了几个方法:
- onVmCreated
- onStarted
- onZygoteInit
- onExit
- 并定义了方法setClassNameAndArgs
- 新增了几个成员:String8 mClassName, Vector mArgs, jclass mClass;
start方法位于AndroidRuntime中定义,我们来看看:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
| void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) { static const String8 startSystemServer("start-system-server"); ... const char* rootDir = getenv("ANDROID_ROOT"); JniInvocation jni_invocation; jni_invocation.Init(NULL); JNIEnv* env; if (startVm(&mJavaVM, &env, zygote) != 0) { return; } onVmCreated(env); 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 { jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V"); if (startMeth == NULL) { ALOGE("JavaVM unable to find main() in '%s'\n", className); } else { env->CallStaticVoidMethod(startClass, startMeth, strArray); #if 0 if (env->ExceptionCheck()) threadExitUncaughtException(env); #endif } } 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"); }
|
其中:
- startVm(): 一系列的虚拟机环境参数配置,最终调用JNI_CreateJavaVM初始化虚拟机,如果方法调用成功,则虚拟机准备完毕,这部分是dalvikVm的知识,以后再研究
- startReg(): 主要通过register_jni_procs来注册jni函数,如register_com_android_internal_os_RuntimeInit、register_android_opengljni…等等jni library
启动虚拟机之后,进入Java世界: ZygoteInit.main()
还是来看代码,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
| public static void main(String argv[]) { ZygoteHooks.startZygoteNoThreadCreation(); try { Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygoteInit"); /开启ddms 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 (Throwable ex) { Log.e(TAG, "Zygote died with exception", ex); closeServerSocket(); throw ex; } }
|
小结,ZygoteInit.main()主要做了几件事情:
- registerZygoteSocket,注册zygote的socket服务,等待其他client的请求
- startSystemServer开启systemserver进程,这是java世界的基石:包含了众多的服务,如AMS, WMS,IMS等等
- 调用runSelectLoop,进入无限循环,等待client请求,来创建进程,每创建一个进程,在子进程中都会抛出异常MethodAndArgsCaller,从而子进程中的代码会运行到caller.run()方法中去
1. registerZygoteSocket()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| private static void registerZygoteSocket(String socketName) { if (sServerSocket == null) { 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); } } }
|
2. startSystemServer()
另外开一篇文章来写吧,这里我们记住,system_server进程,由zygote进程fork出来,然后在创建的虚拟机中执行SystemServer.main()方法
3. runSelectLoop()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| private static void runSelectLoop(String abiList) throws MethodAndArgsCaller { ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>(); ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>(); fds.add(sServerSocket.getFileDescriptor()); peers.add(null); while (true) { StructPollfd[] pollFds = new StructPollfd[fds.size()]; for (int i = 0; i < pollFds.length; ++i) { pollFds[i] = new StructPollfd(); pollFds[i].fd = fds.get(i); pollFds[i].events = (short) POLLIN; } try { Os.poll(pollFds, -1); } catch (ErrnoException ex) { throw new RuntimeException("poll failed", ex); } for (int i = pollFds.length - 1; i >= 0; --i) { if ((pollFds[i].revents & POLLIN) == 0) { continue; } if (i == 0) { ZygoteConnection newPeer = acceptCommandPeer(abiList); peers.add(newPeer); fds.add(newPeer.getFileDesciptor()); } else { boolean done = peers.get(i).runOnce(); if (done) { peers.remove(i); fds.remove(i); } } } } }
|
- 开启sServerSocket,等待客户端请求
- 客户端请求来临,调用ZygoteConnection.runOnce()处理请求
调用ZygoteConnection.runOnce()处理请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| boolean runOnce() throws ZygoteInit.MethodAndArgsCaller { ... args = readArgumentList(); ... int pid = -1; ... pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo, parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet, parsedArgs.appDataDir); try { if (pid == 0) { IoUtils.closeQuietly(serverPipeFd); serverPipeFd = null; handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr); return true; } else { IoUtils.closeQuietly(childPipeFd); childPipeFd = null; return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs); } } finally { IoUtils.closeQuietly(childPipeFd); IoUtils.closeQuietly(serverPipeFd); } }
|
handleChildProc 与 handleParentProc
首先来看 handleChildProc,即zygote进程fork出来的子进程执行的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr) throws ZygoteInit.MethodAndArgsCaller { closeSocket(); ZygoteInit.closeServerSocket(); ... 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 { RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, null ); } }
|
RuntimeInit.zygoteInit
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller { if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote"); Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit"); redirectLogStreams(); commonInit(); nativeZygoteInit(); applicationInit(targetSdkVersion, argv, classLoader); }
|
startThreadPool方法的调用, 参考链接:http://blog.csdn.net/ganyue803/article/details/41484849
1 2 3 4 5 6 7 8
| virtual void onZygoteInit() { sp<ProcessState> proc = ProcessState::self(); ALOGV("App process: starting thread pool.\n"); proc->startThreadPool(); }
|
RuntimeInit.applicationInit
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller { nativeSetExitWithoutCleanup(true); VMRuntime.getRuntime().setTargetHeapUtilization(0.75f); VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion); final Arguments args; try { args = new Arguments(argv); } catch (IllegalArgumentException ex) { Slog.e(TAG, ex.getMessage()); return; } Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); invokeStaticMain(args.startClass, args.startArgs, classLoader); }
|
RuntimeInit.invokeStaticMain
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller { Class<?> cl; try { cl = Class.forName(className, true, classLoader); } catch (ClassNotFoundException ex) { throw new RuntimeException( "Missing class when invoking static main " + className, ex); } Method m; try { m = cl.getMethod("main", new Class[] { String[].class }); } catch (NoSuchMethodException ex) { throw new RuntimeException( "Missing static main on " + className, ex); } catch (SecurityException ex) { throw new RuntimeException( "Problem getting static main on " + className, ex); } int modifiers = m.getModifiers(); if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) { throw new RuntimeException( "Main method is not public and static on " + className); } throw new ZygoteInit.MethodAndArgsCaller(m, argv); }
|
最终,子进程中,调用invokeStaticMain,抛出ZygoteInit.MethodAndArgsCaller异常,从而跳转到ZygoteInit.main()方法的exception处理中,调用caller.run();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public void run() { try { mMethod.invoke(null, new Object[] { mArgs }); } catch (IllegalAccessException ex) { throw new RuntimeException(ex); } catch (InvocationTargetException ex) { Throwable cause = ex.getCause(); if (cause instanceof RuntimeException) { throw (RuntimeException) cause; } else if (cause instanceof Error) { throw (Error) cause; } throw new RuntimeException(ex); } }
|
即,调用ZygoteInit.MethodAndArgsCaller(m, argv)这个main方法,并传参argv
PS: 为采用抛出异常这种方式来跳转呢?
- java中,线程的方法栈中,包含了一个个的栈帧,每个栈帧都是一个方法
- 抛出异常的时候,java会依次将方法栈帧出栈,寻找能够处理异常的栈帧
- 因此,zygote fork出来的子进程,最终会将ZygoteInit.main()方法栈帧上面的栈帧都清空掉
- 从而是的子进程都是从ZygoteInit.mian()方法起栈的
而对于父进程,也就是我们的zygote进程, 来看看handleParentProc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| private boolean handleParentProc(int pid, FileDescriptor[] descriptors, FileDescriptor pipeFd, Arguments parsedArgs) { if (pid > 0) { setChildPgid(pid); } if (descriptors != null) { for (FileDescriptor fd: descriptors) { IoUtils.closeQuietly(fd); } } boolean usingWrapper = false; if (pipeFd != null && pid > 0) { DataInputStream is = new DataInputStream(new FileInputStream(pipeFd)); int innerPid = -1; try { innerPid = is.readInt(); } catch (IOException ex) { Log.w(TAG, "Error reading pid from wrapped process, child may have died", ex); } finally { try { is.close(); } catch (IOException ex) { } } if (innerPid > 0) { int parentPid = innerPid; while (parentPid > 0 && parentPid != pid) { parentPid = Process.getParentPid(parentPid); } if (parentPid > 0) { Log.i(TAG, "Wrapped process has pid " + innerPid); pid = innerPid; usingWrapper = true; } else { Log.w(TAG, "Wrapped process reported a pid that is not a child of " + "the process that we forked: childPid=" + pid + " innerPid=" + innerPid); } } } try { mSocketOutStream.writeInt(pid); mSocketOutStream.writeBoolean(usingWrapper); } catch (IOException ex) { Log.e(TAG, "Error writing to command socket", ex); return true; } return false; }
|
主要做了一些fork清理工作,并没有抛出异常,因此还是在runSelectLoop这个循环中继续往下执行
完结
至此,整个zygote进程的启动流程执行完毕,主要做了以下事情:
- app_main.cpp -> main(), AppRuntime的初始化:创建虚拟机、注册jni函数
- 执行com.android.internal.os.ZygoteInit -> main()函数
- registerZygoteSocket注册服务端sServerSocket
- preload: 基本资源、库的加载
- 如果需要启动systemserver,则启动systemserver进程
- runSelectLoop: 进入无限循环,采用poll + socket的机制,等待client端的请求
6.1 请求过来,fork进程,并在新的进程中运行class的main方法
6.2 父进程做完清理工作,继续在无限循环中执行
参考链接:
http://blog.csdn.net/yaowei514473839/article/details/53022493
http://blog.csdn.net/yaowei514473839/article/details/53045285