美文网首页Android笔记
Android应用进程分裂分析

Android应用进程分裂分析

作者: Young_Allen | 来源:发表于2018-11-05 10:04 被阅读32次

    每天一篇系列:
    强化知识体系,查漏补缺。
    欢迎指正,共同学习!

    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<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(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分裂出来的。

    相关文章

      网友评论

        本文标题:Android应用进程分裂分析

        本文链接:https://www.haomeiwen.com/subject/ruixxqtx.html