Android应用进程分裂分析
每天一篇系列:
强化知识体系,查漏补缺。
欢迎指正,共同学习!
Android终端从断电到上电开始,历经了诸如fastboot,boot,kernel,system等流程,不同Android设备可能有些不同,网上对启动流程的总结大致如下:
图片来源于网上其中Init是Android系统的第一个进程,也是这个文章分析的起点。
Android系统从Init开始,init.c的main函数:
int main(int argc, char **argv){...INFO("property init\n"); property_load_boot_defaults(); INFO("reading config file\n"); init_parse_config_file("/init.rc"); action_for_each_trigger("early-init", action_add_queue_tail); queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done"); queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng"); queue_builtin_action(keychord_init_action, "keychord_init"); queue_builtin_action(console_init_action, "console_init"); /* execute all the boot actions to get us started */ action_for_each_trigger("init", action_add_queue_tail); /* Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random * wasn't ready immediately after wait_for_coldboot_done */ queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng"); queue_builtin_action(property_service_init_action, "property_service_init"); queue_builtin_action(signal_init_action, "signal_init"); /* Don't mount filesystems or start core system services if in charger mode. */ if (is_charger) { action_for_each_trigger("charger", action_add_queue_tail); } else { action_for_each_trigger("late-init", action_add_queue_tail); } ... for(;;) { int nr, i, timeout = -1; execute_one_command(); restart_processes(); if (!property_set_fd_init && get_property_set_fd() > 0) { ufds[fd_count].fd = get_property_set_fd(); ufds[fd_count].events = POLLIN; ufds[fd_count].revents = 0; fd_count++; property_set_fd_init = 1; } if (!signal_fd_init && get_signal_fd() > 0) { ufds[fd_count].fd = get_signal_fd(); ufds[fd_count].events = POLLIN; ufds[fd_count].revents = 0; fd_count++; signal_fd_init = 1; } if (!keychord_fd_init && get_keychord_fd() > 0) { ufds[fd_count].fd = get_keychord_fd(); ufds[fd_count].events = POLLIN; ufds[fd_count].revents = 0; fd_count++; keychord_fd_init = 1; } if (process_needs_restart) { timeout = (process_needs_restart - gettime()) * 1000; if (timeout < 0) timeout = 0; } if (!action_queue_empty() || cur_action) timeout = 0;#if BOOTCHART if (bootchart_count > 0) { if (timeout < 0 || timeout > BOOTCHART_POLLING_MS) timeout = BOOTCHART_POLLING_MS; if (bootchart_step() < 0 || --bootchart_count == 0) { bootchart_finish(); bootchart_count = 0; } }#endif nr = poll(ufds, fd_count, timeout); if (nr <= 0) continue; for (i = 0; i < fd_count; i++) { if (ufds[i].revents & POLLIN) { if (ufds[i].fd == get_property_set_fd()) handle_property_set_fd(); else if (ufds[i].fd == get_keychord_fd()) handle_keychord(); else if (ufds[i].fd == get_signal_fd()) handle_signal(); } } } return 0;}
在main里面主要解析了init.*.rc文件,对SECTION,OPTION,COMMAND。
在解析rc文件时,区分了early-init,init,early-boot,boot四个阶段,其次就是Service的启动。
在init.rc中的有一个COMMAND为class_start default,对应着启动zygote进程。
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
zygote在service_start函数中通过fork和execve共同创建。
然后初始化了Properties服务相关的内容,其中涉及到mmap共享内存,最大可以记录247条Properties。
zygote对应的原型是app_process,其源码是App_main.cpp:
int main(int argc, char* const argv[]){ ... 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; } } ... if (zygote) { 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.\n"); app_usage(); LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); return 10; }}
使用AndroidRuntime.cpp去创建一个JavaVM虚拟机,加载JNI,配置运行环境等。然后通过JNI的反射机制,去调用com.android.internal.os.ZygoteInit的main函数。到这里就完成了从init.rc到AndroidRuntime直到Java的调用,到Java后的第一函数就是ZygoteInit的main函数。
在Zygote孵化进程中,处理startSystemServer的启动:
private static boolean startSystemServer(String abiList, String socketName) throws MethodAndArgsCaller, RuntimeException {... 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) { if (hasSecondZygote(abiList)) { waitForSecondaryZygote(socketName); } handleSystemServerProcess(parsedArgs); } return true; }
在这个处理中forkSystemServer孵化出SystemServer进程,并最终会调用到SystemServer中的load1和load2流程,其中分为:
// Start services. try { startBootstrapServices(); startCoreServices(); startOtherServices(); } catch (Throwable ex) { Slog.e("System", "******************************************"); Slog.e("System", "************ Failure starting system services", ex); throw ex; }
把服务大致分成了三类,预启动服务类、核心服务类以及其他服务类。到这里可以看到这些Service还是运行在SystemServer的进程里面。也就是说服务运行在system_process里。
BootstrapServices是包含了几个在启动核心服务之前准备好的服务类:
private void startBootstrapServices() { // Wait for installd to finish starting up so that it has a chance to // create critical directories such as /data/user with the appropriate // permissions. We need this to complete before we initialize other services. mInstaller = mSystemServiceManager.startService(Installer.class); // Activity manager runs the show. mActivityManagerService = mSystemServiceManager.startService( ActivityManagerService.Lifecycle.class).getService(); mActivityManagerService.setSystemServiceManager(mSystemServiceManager); // Power manager needs to be started early because other services need it. // Native daemons may be watching for it to be registered so it must be ready // to handle incoming binder calls immediately (including being able to verify // the permissions for those calls). mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class); // Now that the power manager has been started, let the activity manager // initialize power management features. mActivityManagerService.initPowerManagement(); // Display manager is needed to provide display metrics before package manager // starts up. mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class); // We need the default display before we can initialize the package manager. mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY); // Only run "core" apps if we're encrypting the device. String cryptState = SystemProperties.get("vold.decrypt"); if (ENCRYPTING_STATE.equals(cryptState)) { Slog.w(TAG, "Detected encryption in progress - only parsing core apps"); mOnlyCore = true; } else if (ENCRYPTED_STATE.equals(cryptState)) { Slog.w(TAG, "Device encrypted - only parsing core apps"); mOnlyCore = true; } // Start the package manager. Slog.i(TAG, "Package Manager"); mPackageManagerService = PackageManagerService.main(mSystemContext, mInstaller, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore); mFirstBoot = mPackageManagerService.isFirstBoot(); mPackageManager = mSystemContext.getPackageManager(); Slog.i(TAG, "User Service"); ServiceManager.addService(Context.USER_SERVICE, UserManagerService.getInstance()); // Initialize attribute cache used to cache resources from packages. AttributeCache.init(mSystemContext); // Set up the Application instance for the system process and get started. mActivityManagerService.setSystemProcess(); }
CoreServices包含了几个核心服务类的启动:
/** * Starts some essential services that are not tangled up in the bootstrap process. */ private void startCoreServices() { // Manages LEDs and display backlight. mSystemServiceManager.startService(LightsService.class); // Tracks the battery level. Requires LightService. mSystemServiceManager.startService(BatteryService.class); // Tracks application usage stats. mSystemServiceManager.startService(UsageStatsService.class); mActivityManagerService.setUsageStatsManager( LocalServices.getService(UsageStatsManagerInternal.class)); // Tracks whether the updatable WebView is in a ready state and watches for update installs. mSystemServiceManager.startService(WebViewUpdateService.class); }
在SystemServer中,各种服务准备之前必须保证ActivityManagerService已经准备好,可见AMS的重要性:
private void startOtherServices() { ... mActivityManagerService.systemReady(new Runnable() { @Override public void run() { Slog.i(TAG, "Making services ready"); mSystemServiceManager.startBootPhase( SystemService.PHASE_ACTIVITY_MANAGER_READY); try { mActivityManagerService.startObservingNativeCrashes(); } catch (Throwable e) { reportWtf("observing native crashes", e); } Slog.i(TAG, "WebViewFactory preparation"); WebViewFactory.prepareWebViewInSystemServer(); try { startSystemUi(context); } catch (Throwable e) { reportWtf("starting System UI", e); } try { if (mountServiceF != null) mountServiceF.systemReady(); } catch (Throwable e) { reportWtf("making Mount Service ready", e); } try { if (networkScoreF != null) networkScoreF.systemReady(); } catch (Throwable e) { reportWtf("making Network Score Service ready", e); } try { if (networkManagementF != null) networkManagementF.systemReady(); } catch (Throwable e) { reportWtf("making Network Managment Service ready", e); } try { if (networkStatsF != null) networkStatsF.systemReady(); } catch (Throwable e) { reportWtf("making Network Stats Service ready", e); } try { if (networkPolicyF != null) networkPolicyF.systemReady(); } catch (Throwable e) { reportWtf("making Network Policy Service ready", e); } try { if (connectivityF != null) connectivityF.systemReady(); } catch (Throwable e) { reportWtf("making Connectivity Service ready", e); } try { if (audioServiceF != null) audioServiceF.systemReady(); } catch (Throwable e) { reportWtf("Notifying AudioService running", e); } Watchdog.getInstance().start(); // It is now okay to let the various system services start their // third party code... mSystemServiceManager.startBootPhase( SystemService.PHASE_THIRD_PARTY_APPS_CAN_START); try { if (wallpaperF != null) wallpaperF.systemRunning(); } catch (Throwable e) { reportWtf("Notifying WallpaperService running", e); } try { if (immF != null) immF.systemRunning(statusBarF); } catch (Throwable e) { reportWtf("Notifying InputMethodService running", e); } try { if (locationF != null) locationF.systemRunning(); } catch (Throwable e) { reportWtf("Notifying Location Service running", e); } try { if (countryDetectorF != null) countryDetectorF.systemRunning(); } catch (Throwable e) { reportWtf("Notifying CountryDetectorService running", e); } try { if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemRunning(); } catch (Throwable e) { reportWtf("Notifying NetworkTimeService running", e); } try { if (commonTimeMgmtServiceF != null) { commonTimeMgmtServiceF.systemRunning(); } } catch (Throwable e) { reportWtf("Notifying CommonTimeManagementService running", e); } try { if (textServiceManagerServiceF != null) textServiceManagerServiceF.systemRunning(); } catch (Throwable e) { reportWtf("Notifying TextServicesManagerService running", e); } try { if (atlasF != null) atlasF.systemRunning(); } catch (Throwable e) { reportWtf("Notifying AssetAtlasService running", e); } try { // TODO(BT) Pass parameter to input manager if (inputManagerF != null) inputManagerF.systemRunning(); } catch (Throwable e) { reportWtf("Notifying InputManagerService running", e); } try { if (telephonyRegistryF != null) telephonyRegistryF.systemRunning(); } catch (Throwable e) { reportWtf("Notifying TelephonyRegistry running", e); } try { if (mediaRouterF != null) mediaRouterF.systemRunning(); } catch (Throwable e) { reportWtf("Notifying MediaRouterService running", e); } try { if (mmsServiceF != null) mmsServiceF.systemRunning(); } catch (Throwable e) { reportWtf("Notifying MmsService running", e); } } }); }
在AMS的systemReady阶段
public void systemReady(final Runnable goingCallback) { synchronized(this) { if (mSystemReady) { // If we're done calling all the receivers, run the next "boot phase" passed in // by the SystemServer if (goingCallback != null) { goingCallback.run(); } return; } ... // Start up initial activity. mBooting = true; startHomeActivityLocked(mCurrentUserId); ... }
在startHomeActivityLocked处理中又会涉及到ActivityStack、ActivityThread等启动一个APK进程。
当需要启动一个apk时,从流程分析上来看,会通过ActivityManagerService的startProcessLocked来孵化出一条新的进程:
private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) { ... if (entryPoint == null) entryPoint = "android.app.ActivityThread"; checkTime(startTime, "startProcess: asking zygote to start proc"); 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!"); ...
Process类是Android原生的类,而不是Java包中的Process。传入的参数名是android.app.ActivityThread,在后面孵化进程时会使用到:
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) { try { 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); } } private 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 { ... return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote); } } private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx { if (primaryZygoteState == null || primaryZygoteState.isClosed()) { try { primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET); } catch (IOException ioe) { throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe); } } if (primaryZygoteState.matches(abi)) { return primaryZygoteState; } // The primary zygote didn't match. Try the secondary. if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) { try { secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET); } catch (IOException ioe) { throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe); } } if (secondaryZygoteState.matches(abi)) { return secondaryZygoteState; } throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi); }
在这里可以看到ZygoteState.connect(ZYGOTE_SOCKET),通过sockect去和zygote通信了。在zygote模块有一个一直循环的looper,用来处理其他模块发过来的sockect信息:
private static void runSelectLoop(String abiList) throws MethodAndArgsCaller { ArrayList fds = new ArrayList(); ArrayList peers = new ArrayList(); 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(abiList); peers.add(newPeer); fds.add(newPeer.getFileDescriptor()); } else { boolean done; done = peers.get(index).runOnce(); if (done) { peers.remove(index); fds.remove(index); } } } }
在ZygoteConnection的runOnce处理其他模块发给Zygote的socket消息:
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller { ... 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) { // in child IoUtils.closeQuietly(serverPipeFd); serverPipeFd = null; handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr); // should never get here, the child is expected to either // throw ZygoteInit.MethodAndArgsCaller or exec(). return true; } else { // in parent...pid of < 0 means failure IoUtils.closeQuietly(childPipeFd); childPipeFd = null; return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs); } } finally { IoUtils.closeQuietly(childPipeFd); IoUtils.closeQuietly(serverPipeFd); } }
public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags, int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, String instructionSet, String appDataDir) { long startTime = SystemClock.elapsedRealtime(); VM_HOOKS.preFork(); checkTime(startTime, "Zygote.preFork"); int pid = nativeForkAndSpecialize( uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose, instructionSet, appDataDir); checkTime(startTime, "Zygote.nativeForkAndSpecialize"); VM_HOOKS.postForkCommon(); checkTime(startTime, "Zygote.postForkCommon"); return pid; }
private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr) throws ZygoteInit.MethodAndArgsCaller { ... if (parsedArgs.invokeWith != null) { WrapperInit.execStandalone(parsedArgs.invokeWith, parsedArgs.classpath, className, mainArgs); } else { ClassLoader cloader; if (parsedArgs.classpath != null) { cloader = new PathClassLoader(parsedArgs.classpath, ClassLoader.getSystemClassLoader()); } else { cloader = ClassLoader.getSystemClassLoader(); } try { ZygoteInit.invokeStaticMain(cloader, className, mainArgs); } catch (RuntimeException ex) { logAndPrintError(newStderr, "Error starting.", ex); } } } }
分析到这个地方,大概应该清楚了在需要新启动一个进程时,实际上是通过sockect消息发送给zygote,让zygote去孵化出一个进程来。并且在ZygoteInit.invokeStaticMain(cloader, className, mainArgs)通过main函数开始执行这个孵化进程,例如启动一个应用时,实际上是ActivityThread的main函数开始执行。应用进程就是这样一个一个通过zygote分裂出来的。
更多相关文章
- C语言函数的递归(上)
- 【腾讯Bugly干货分享】Android进程保活招式大全
- 理解Android系统的进程间通信原理(二)----RPC机制
- 框架层理解Activity生命周期(APP启动过程)
- Android性能测试工具APT使用指南
- Android中app进程ABI确定过程
- Android函数响应式编程最新RxJava-操作符入门(2)
- android 解决getColor()方法过时
- 通信之进程间通信-AIDL