The communication method of the AMS process in android notifying the Zygote process to fork the new process

 Android system startup

1, "Introduction to the Android System Startup Process"

2, "Android init process startup process"

3. "Android zygote process startup process"

4. "Android SystemServer Process Startup Process"

5. "Android launcher startup process"

6. "Detailed Explanation of Android Activity Startup Process"

Android System Development Preparation

1, "Android Source Code Download and Compilation"

2. "Android 11 source code compilation and pixel3 flashing"

3. "Android Framework Code IDE Loading and Debugging"

Android System Development Practice

1. "Android Setting Default Input Method"

2, "android framework prefabricated APK application"

3. "Detailed Explanation of Restricting Apps from Starting at the Android System Level"

4. "Android compiles the framework module separately and pushes it"

5. "Android Framework Development System Problem Analysis"

Android System Development Core Knowledge Reserve

1, "Android Compilation System - envsetup and lunch code articles"

2. "Android Compilation System - Concept"

3. "Detailed Explanation of Android Log System"

4. "Android System Handler Detailed Explanation"

5. "Android System Binder Detailed Explanation"

6. "Detailed Explanation of the Relationship between Activity, View and Window in Android"

7. "Detailed Explanation of the Android View Drawing Process"

8. "Detailed Explanation of Android Reading System Attributes"

9. "Detailed Explanation of Android Window Management Mechanism"

10. "Acquaintance with Android System"

11. "The communication method of AMS process in android notifying Zygote process fork new process"

Detailed explanation of Android core functions

1. "Android application market click to download APK installation details"

2, "Android gesture navigation (swipe from bottom to top to enter the multitasking page)"

3. "Android Gesture Analysis (Swipe left to right on the application interface to exit the application)"

4. "Detailed Explanation of Android Application Installation Process"

5, "android11 ​​installation application triggers desktop icon refresh process"

6. "Detailed Explanation of Android System Multitasking Recents"

7. "Android System Navigation Bar View Analysis"

———————————————————————————————————————————

Table of contents

1. Background introduction

Second, the application process startup process

Three, reason analysis


1. Background introduction

        When AMS notifies Zygote to fork the process, it uses socket instead of binder. We all know that the way to cross processes in Android is binder, but why use Socket here? Some people will say that LocalSocket is originally used for local inter-process communication, which is true, but it is more important to know why.

Second, the application process startup process

        When the android system clicks the APP icon on the desktop, if the application process does not exist, it will notify the zygote process to fork a new process through AMS. The startup process is as follows:

1. Implemented in the startProcessLocked method of ActivityManagerService, the path frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

    final ProcessRecord startProcessLocked(String processName,
            ApplicationInfo info, boolean knownToBeDead, int intentFlags,
            HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,
            boolean isolated, boolean keepIfLarge) {
        return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
                hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,
                keepIfLarge, null /* ABI override */, null /* entryPoint */,
                null /* entryPointArgs */, null /* crashHandler */);
    }

2. Call to frameworks/base/services/core/java/com/android/server/am/ProcessList.java,

 private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,
            ProcessRecord app, int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags,
            int mountExternal, String seInfo, String requiredAbi, String instructionSet,
            String invokeWith, long startTime) {

-----------------------------------------------------------------------------
if (hostingRecord.usesWebviewZygote()) {
                startResult = startWebView(entryPoint,
                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, null, app.info.packageName, app.mDisabledCompatChanges,
                        new String[]{PROC_START_SEQ_IDENT + app.startSeq});
            } else if (hostingRecord.usesAppZygote()) {
                final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);

                // We can't isolate app data and storage data as parent zygote already did that.
                startResult = appZygote.getProcess().start(entryPoint,
                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, null, app.info.packageName,
                        /*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,
                        app.mDisabledCompatChanges, pkgDataInfoMap, whitelistedAppDataInfoMap,
                        false, false,
                        new String[]{PROC_START_SEQ_IDENT + app.startSeq});
            } else {
                startResult = Process.start(entryPoint,
                        app.processName, uid, uid, gids, runtimeFlags, mountExternal,
                        app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                        app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags,
                        isTopApp, app.mDisabledCompatChanges, pkgDataInfoMap,
                        whitelistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,
                        new String[]{PROC_START_SEQ_IDENT + app.startSeq});
            }

-------------------------------------------------------------------------------
}

3,调用frameworks/base/core/java/android/os/Process.java

    public static ProcessStartResult start(@NonNull final String processClass,
                                           @Nullable final String niceName,
                                           int uid, int gid, @Nullable int[] gids,
                                           int runtimeFlags,
                                           int mountExternal,
                                           int targetSdkVersion,
                                           @Nullable String seInfo,
                                           @NonNull String abi,
                                           @Nullable String instructionSet,
                                           @Nullable String appDataDir,
                                           @Nullable String invokeWith,
                                           @Nullable String packageName,
                                           int zygotePolicyFlags,
                                           boolean isTopApp,
                                           @Nullable long[] disabledCompatChanges,
                                           @Nullable Map<String, Pair<String, Long>>
                                                   pkgDataInfoMap,
                                           @Nullable Map<String, Pair<String, Long>>
                                                   whitelistedDataInfoMap,
                                           boolean bindMountAppsData,
                                           boolean bindMountAppStorageDirs,
                                           @Nullable String[] zygoteArgs) {
        return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, packageName,
                    zygotePolicyFlags, isTopApp, disabledCompatChanges,
                    pkgDataInfoMap, whitelistedDataInfoMap, bindMountAppsData,
                    bindMountAppStorageDirs, zygoteArgs);
    }

4,路径frameworks/base/core/java/android/os/ZygoteProcess.java,

    private Process.ProcessStartResult startViaZygote(@NonNull final String processClass,
                                                      @Nullable final String niceName,
                                                      final int uid, final int gid,
                                                      @Nullable final int[] gids,
                                                      int runtimeFlags, int mountExternal,
                                                      int targetSdkVersion,
                                                      @Nullable String seInfo,
                                                      @NonNull String abi,
                                                      @Nullable String instructionSet,
                                                      @Nullable String appDataDir,
                                                      @Nullable String invokeWith,
                                                      boolean startChildZygote,
                                                      @Nullable String packageName,
                                                      int zygotePolicyFlags,
                                                      boolean isTopApp,
                                                      @Nullable long[] disabledCompatChanges,
                                                      @Nullable Map<String, Pair<String, Long>>
                                                              pkgDataInfoMap,
                                                      @Nullable Map<String, Pair<String, Long>>
                                                              whitelistedDataInfoMap,
                                                      boolean bindMountAppsData,
                                                      boolean bindMountAppStorageDirs,
                                                      @Nullable String[] extraArgs)
                                                      throws ZygoteStartFailedEx {

-------------------------------------------------------------------------------
synchronized(mLock) {
            // The USAP pool can not be used if the application will not use the systems graphics
            // driver.  If that driver is requested use the Zygote application start path.
            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
                                              zygotePolicyFlags,
                                              argsForZygote);
        }


-------------------------------------------------------------------------------


}

5. Among them, the key calls are as follows,

    /**
     * Tries to open a session socket to a Zygote process with a compatible ABI if one is not
     * already open. If a compatible session socket is already open that session socket is returned.
     * This function may block and may have to try connecting to multiple Zygotes to find the
     * appropriate one.  Requires that mLock be held.
     */
    @GuardedBy("mLock")
    private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
        try {
            attemptConnectionToPrimaryZygote();

            if (primaryZygoteState.matches(abi)) {
                return primaryZygoteState;
            }

            if (mZygoteSecondarySocketAddress != null) {
                // The primary zygote didn't match. Try the secondary.
                attemptConnectionToSecondaryZygote();

                if (secondaryZygoteState.matches(abi)) {
                    return secondaryZygoteState;
                }
            }
        } catch (IOException ioe) {
            throw new ZygoteStartFailedEx("Error connecting to zygote", ioe);
        }

        throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
    }

        The zygoteSendArgsAndGetResult method is called, the incoming parameter is openZygoteSocketIfNeeded return value ZygoteState, ZygoteState is the static internal class of ZygoteProcess, which indicates the communication state with the ZYgote process. openZygoteSocketIfNeeded actually establishes a connection with the Socket created in the Zogote process . After that is the process of socket communication.

Three, reason analysis

        In the second part of the application process startup process, it can be seen that when AMS notifies Zygote to fork the process, it uses the socket method instead of the binder. Why is android designed like this? If binder is used to implement, what problems will it cause?

        In the POSIX standard, the behavior of fork is this: copy the data of the entire user space, usually using the copy-on-write strategy, so it can be achieved very quickly) and all system objects, and then copy only the current thread to the child process . Here, all other threads in the parent process (except the thread currently executing the fork thread) suddenly evaporate in the child process.
        For locks, from the perspective of the OS, each lock has an owner, that is, the thread that locked it last time. Assuming such an environment, before fork, a child thread locks a certain lock and obtains ownership of the lock. After fork, all other threads in the child process disappear. However, the lock is copied normally. From the perspective of the child process, this lock has no owner without this lock, so no one can unlock it. When the child process wants to unlock the lock, there is no longer any way to unlock it, and the program deadlocks.

    To sum up, it is afraid that the parent process binder thread has a lock, and then the main thread of the child process has been waiting for the resources of its child thread (the child process copied from the parent process), but in fact the child process of the parent process has not been copied, resulting in Deadlock, so fork does not allow multithreading. Coincidentally, Binder communication happens to be multi-threaded, so the parent process (Zgote) simply does not use binder threads at this time.

Guess you like

Origin blog.csdn.net/allen_xu_2012_new/article/details/131067430