应用程序进程启动过程

news2024/5/18 17:19:54

1 应用程序进程简介

想要启动一个应用程序,首先要保证这个应用程序所需要的应用程序进程已经启动。 AMS 在启动应用程序时会检查这个应用程序所需要的应用程序进程是否已经存在,如果不存在就会请求 Zygote 进程启动需要的应用程序进程。 在 Zygote进程启动过程 中可以知道,在 ZygoteInit.main 方法中会创建一个 Server 端的 Socket 用来等待 AMS 请求 Zygote 进程创建子进程。Zygote 进程通过 fork 自身创建子进程,这样,子进程就会获得 Zygote 进程在启动时创建的 Java 虚拟机实例。

在应用程序的创建过程中,除了获取 Java 虚拟机的实例外,还创建了 Binder 线程池和消息循环,这样运行应用进程中的应用程序就可以使用 Binder 进行进程间通信以及处理消息了。

2 应用程序进程启动过程

应用程序进程创建的过程比较复杂,这里分为两部分, AMS 发送启动应用程序进程请求和 Zygote 接收请求并创建应用程序进程。

2.1 AMS 发送启动应用程序进程请求

以下是相关时序图:

AMS发送启动应用程序进程请求

ActivityManagerServive 如果想要启动应用程序进程,就需要向 Zygote 进程发送创建应用程序进程的请求。AMS 是通过调用 ActivityManagerService.LocalService.startProcess 方法向 Zygote 进程发送请求的,代码如下所示:

// /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public final class LocalService extends ActivityManagerInternal {
    @Override
    public void startProcess(String processName, ApplicationInfo info,
                             boolean knownToBeDead, String hostingType, 
                             ComponentName hostingName) {
        try {
            if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "startProcess:"
                                 + processName);
            }
            synchronized (ActivityManagerService.this) {
                startProcessLocked(processName, info, knownToBeDead, 
                                   0 /* intentFlags */,
                                   new HostingRecord(hostingType, hostingName),
                                   false /* allowWhileBooting */, 
                                   false /* isolated */,
                                   true /* keepIfLarge */); // 1
            }
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        }
    }
    
    @GuardedBy("this")
    final ProcessRecord startProcessLocked(String processName,
                                           ApplicationInfo info, 
                                           boolean knownToBeDead, int intentFlags,
                                           HostingRecord hostingRecord, 
                                           boolean allowWhileBooting, 
                                           boolean isolated, boolean keepIfLarge) {
        return mProcessList.startProcessLocked(processName, info, knownToBeDead, 
                                               intentFlags,
                                               hostingRecord, allowWhileBooting, 
                                               isolated, 0 /* isolatedUid */, 
                                               keepIfLarge,
                                               null /* ABI override */, 
                                               null /* entryPoint */, 
                                               null /* entryPointArgs */,
                                               null /* crashHandler */); // 2
    }
}

在注释 2 处调用 ProcessList.startProcessLocked 方法,如下所示:

// /frameworks/base/services/core/java/com/android/server/am/ProcessList.java
@GuardedBy("mService")
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
                                       boolean knownToBeDead, int intentFlags, 
                                       HostingRecord hostingRecord,
                                       boolean allowWhileBooting, boolean isolated, 
                                       int isolatedUid, boolean keepIfLarge,
                                       String abiOverride, String entryPoint, 
                                       String[] entryPointArgs, Runnable crashHandler) {
    ...
    final boolean success = startProcessLocked(app, hostingRecord, abiOverride);
    ...
}

@GuardedBy("mService")
final boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
                                 String abiOverride) {
    return startProcessLocked(app, hostingRecord, false /* disableHiddenApiChecks */, 
                              false /* mountExtStorageFull */, abiOverride);
}

@GuardedBy("mService")
boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
                           boolean disableHiddenApiChecks, boolean mountExtStorageFull,
                           String abiOverride) {
    ...
    int uid = app.uid; // 1 获取要创建的应用程序进程的用户 ID
    int[] gids = null;
    int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
    if (!app.isolated) {
		...
        // 2. 对 gids 进行创建和赋值
        if (ArrayUtils.isEmpty(permGids)) {
            gids = new int[3];
        } else {
            gids = new int[permGids.length + 3];
            System.arraycopy(permGids, 0, gids, 3, permGids.length);
        }
        gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
        gids[1] = UserHandle.getCacheAppGid(UserHandle.getAppId(uid));
        gids[2] = UserHandle.getUserGid(UserHandle.getUserId(uid));

    }
    ...
    final String entryPoint = "android.app.ActivityThread"; // 3
    return startProcessLocked(hostingRecord, entryPoint, app, uid, gids, runtimeFlags, 
                              mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,
                              startTime);
}

@GuardedBy("mService")
boolean startProcessLocked(HostingRecord hostingRecord, String entryPoint,
                           ProcessRecord app, int uid, int[] gids, int runtimeFlags, 
                           int mountExternal, String seInfo, String requiredAbi, 
                           String instructionSet, String invokeWith, long startTime) {
	...
    final Process.ProcessStartResult startResult = startProcess(hostingRecord, entryPoint, app, 
                                                                uid, gids, runtimeFlags, 
                                                                mountExternal, seInfo, 
                                                                requiredAbi, instructionSet,
                                                                invokeWith, startTime);
    ...
}

private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,
                                                ProcessRecord app, int uid, int[] gids, 
                                                int runtimeFlags, int mountExternal,
                                                String seInfo, String requiredAbi, 
                                                String instructionSet, String invokeWith,
                                                long startTime) {
	...
    // 4 启动应用程序进程
    startResult = Process.start(entryPoint, app.processName, uid, uid, gids, runtimeFlags, 
                                mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, 
                                instructionSet, app.info.dataDir, invokeWith, 
                                app.info.packageName, 
                                new String[] {PROC_START_SEQ_IDENT + app.startSeq});
	...
}

在注释 1 处得到要创建的进程的用户 ID,在注释 2 处对用户组 IDgids) 进行创建和赋值。在注释 3 处将 entryPoint 赋值为 android.app.ActivityThread ,这个值就是应用程序进程主线程的类名。 在注释 4 处调用 Process.start 方法,将此前得到的进程的用户 ID 和用户组 ID 传进去。继续看 Process.start 方法:

// /frameworks/base/core/java/android/os/Process.java
public static final ZygoteProcess ZYGOTE_PROCESS = new ZygoteProcess();

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,
                                       @Nullable String[] zygoteArgs) {
    return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
                                runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                                abi, instructionSet, appDataDir, invokeWith, packageName,
                                /*useUsapPool=*/ true, zygoteArgs); // 1
}

Process.start 方法中调用了 ZygoteProcess.start 方法,其中,ZygoteProcess 类用于保持与 Zygote 进程的通信状态,ZygoteProcess.start 方法如下所示:

// /frameworks/base/core/java/android/os/ZygoteProcess.java
public final Process.ProcessStartResult start(@NonNull final String processClass,
                                              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,
                                              boolean useUsapPool,
                                              @Nullable String[] zygoteArgs) {
    // TODO (chriswailes): Is there a better place to check this value?
    if (fetchUsapPoolEnabledPropWithMinInterval()) {
        informZygotesOfUsapPoolStatus();
    }

    try {
        return startViaZygote(processClass, niceName, uid, gid, gids,
                              runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                              abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ 
                              false, packageName, useUsapPool, zygoteArgs); // 1
    } catch (ZygoteStartFailedEx ex) {
        Log.e(LOG_TAG, "Starting VM process through Zygote failed");
        throw new RuntimeException("Starting VM process through Zygote failed", ex);
    }
}

在注释 1 处调用了 ZygoteProcess.startViaZygote 方法,代码如下所示:

// /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,
                                                  boolean useUsapPool,
                                                  @Nullable String[] extraArgs)
    											throws ZygoteStartFailedEx {
    // 1 创建字符串列表 argsForZygote,并将应用进程的启动参数保存在 argForZygote 中
    ArrayList<String> argsForZygote = new ArrayList<>();
    // --runtime-args, --setuid=, --setgid=,
    // and --setgroups= must go first
    argsForZygote.add("--runtime-args");
    argsForZygote.add("--setuid=" + uid);
    argsForZygote.add("--setgid=" + gid);
    argsForZygote.add("--runtime-flags=" + runtimeFlags);
	...
    synchronized(mLock) {
        // 2
        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), // 3
                                          useUsapPool, argsForZygote); 
    }

}

在注释 1 处创建了字符串列表 argsForZygote,并将启动应用程序进程的启动参数保存在 argsForZygote 中,方法最终会调用 ZygoteProcess.zygoteSendArgsAndGetResult 方法,需要注意的是,ZygoteProcess.zygoteSendArgsAndGetResult 的第一个参数是 ZygoteProcess.openZygoteSocketIfNeeded 方法。ZygoteProcess.zygoteSendArgsAndGetResult 方法如下所示:

// /frameworks/base/core/java/android/os/ZygoteProcess.java
@GuardedBy("mLock")
private Process.ProcessStartResult zygoteSendArgsAndGetResult(
    ZygoteState zygoteState, boolean useUsapPool, @NonNull ArrayList<String> args)
    throws ZygoteStartFailedEx {
    for (String arg : args) {
        if (arg.indexOf('\n') >= 0) {
            throw new ZygoteStartFailedEx("Embedded newlines not allowed");
        } else if (arg.indexOf('\r') >= 0) {
            throw new ZygoteStartFailedEx("Embedded carriage returns not allowed");
        }
    }

    String msgStr = args.size() + "\n" + String.join("\n", args) + "\n";

    if (useUsapPool && mUsapPoolEnabled && canAttemptUsap(args)) {
        try {
            return attemptUsapSendArgsAndGetResult(zygoteState, msgStr);
        } catch (IOException ex) {
            Log.e(LOG_TAG, "IO Exception while communicating with USAP pool - "
                  + ex.getMessage());
        }
    }

    return attemptZygoteSendArgsAndGetResult(zygoteState, msgStr); // 1
}

private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult(
    ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx {
    try {
        final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter; // 2
        final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;

        zygoteWriter.write(msgStr);
        zygoteWriter.flush();

        // Always read the entire result from the input stream to avoid leaving
        // bytes in the stream for future process starts to accidentally stumble
        // upon.
        Process.ProcessStartResult result = new Process.ProcessStartResult();
        result.pid = zygoteInputStream.readInt();
        result.usingWrapper = zygoteInputStream.readBoolean();

        if (result.pid < 0) {
            throw new ZygoteStartFailedEx("fork() failed");
        }

        return result;
    } catch (IOException ex) {
        zygoteState.close();
        Log.e(LOG_TAG, "IO Exception while communicating with Zygote - "
              + ex.toString());
        throw new ZygoteStartFailedEx(ex);
    }
}

ZygoteProcess.zygoteSendArgsAndGetResult 方法的主要作用就是将传入的引用进程的启动参数 args 写入到 ZygoteState 中。ZygoteStateZygoteProcess 的镜头内部类,用于表示与 Zygote 进程的通信状态,ZygoteState 是由 ZygoteProcess.openZygoteSocketIfNeeded 方法返回的,以下是 ZygoteProcess.openZygoteSocketIfNeeded 方法的代码:

// /frameworks/base/core/java/android/os/ZygoteProcess.java
@GuardedBy("mLock")
private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
    try {
        // 尝试与 Zygote 进程建立连接
        attemptConnectionToPrimaryZygote(); // 1
		// 连接 Zygote 主模式返回的 ZygoteState 是否与启动应用程序进程所需要的 ABI 匹配
        if (primaryZygoteState.matches(abi)) { // 2
            return primaryZygoteState;
        }

        if (mZygoteSecondarySocketAddress != null) {
            // The primary zygote didn't match. Try the secondary. 如果不匹配,则尝试连接 Zygote 辅模式
            attemptConnectionToSecondaryZygote(); // 3

            // 连接 Zygote 辅模式返回的 ZygoteState 是否与启动因公程序进程所需要的 ABI 匹配
            if (secondaryZygoteState.matches(abi)) { // 4
                return secondaryZygoteState;
            }
        }
    } catch (IOException ioe) {
        throw new ZygoteStartFailedEx("Error connecting to zygote", ioe);
    }

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

/**
  * Creates a ZygoteState for the primary zygote if it doesn't exist or has been disconnected.
  */
@GuardedBy("mLock")
private void attemptConnectionToPrimaryZygote() throws IOException {
    if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
        primaryZygoteState =
            ZygoteState.connect(mZygoteSocketAddress, mUsapPoolSocketAddress); // 5

        maybeSetApiBlacklistExemptions(primaryZygoteState, false);
        maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);
        maybeSetHiddenApiAccessStatslogSampleRate(primaryZygoteState);
    }
}

/**
  * Creates a ZygoteState for the secondary zygote if it doesn't exist or has been disconnected.
  */
@GuardedBy("mLock")
private void attemptConnectionToSecondaryZygote() throws IOException {
    if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
        secondaryZygoteState =
            ZygoteState.connect(mZygoteSecondarySocketAddress, mUsapPoolSecondarySocketAddress); // 6

        maybeSetApiBlacklistExemptions(secondaryZygoteState, false);
        maybeSetHiddenApiAccessLogSampleRate(secondaryZygoteState);
        maybeSetHiddenApiAccessStatslogSampleRate(secondaryZygoteState);
    }
}  

Zygote 进程启动的过程中,会在 Zygote.main 方法中创建 namezygoteServer 端的 Socket。在注释 5 处会调用 ZygoteState.connect 方法与名称为 PRIMARY_SOCKET_NAMESocket 建立连接并返回 ZygoteState 类型的变量 primaryZygoteState 对象,PRIMARY_SOCKET_NAME 的值为 zygote。在注释 3 处,如果 primaryZygoteState 与启动应用用程序进程所需的 ABI 不匹配,则会在注释 6 处连接 namezygote_secondarySocket。如果这两种模式都不匹配则抛出异常。

Zygote 的启动脚本有 4 种,如果采用的是 init.zygote32_64.rc 或者 init.zygote64_32.rc,则 namezygote 为主模式,namezygote_secondary 为辅模式。

// frameworks/base/core/java/com/android/internal/os/Zygote.java
public static final String PRIMARY_SOCKET_NAME = "zygote";
public static final String SECONDARY_SOCKET_NAME = "zygote_secondary";
public static final String USAP_POOL_PRIMARY_SOCKET_NAME = "usap_pool_primary";
public static final String USAP_POOL_SECONDARY_SOCKET_NAME = "usap_pool_secondary";

// /frameworks/base/core/java/android/os/ZygoteProcess.java
public ZygoteProcess() {
    mZygoteSocketAddress =
        new LocalSocketAddress(Zygote.PRIMARY_SOCKET_NAME, 
                               LocalSocketAddress.Namespace.RESERVED);
    mZygoteSecondarySocketAddress =
        new LocalSocketAddress(Zygote.SECONDARY_SOCKET_NAME,
                               LocalSocketAddress.Namespace.RESERVED);

    mUsapPoolSocketAddress =
        new LocalSocketAddress(Zygote.USAP_POOL_PRIMARY_SOCKET_NAME,
                               LocalSocketAddress.Namespace.RESERVED);
    mUsapPoolSecondarySocketAddress =
        new LocalSocketAddress(Zygote.USAP_POOL_SECONDARY_SOCKET_NAME,
                               LocalSocketAddress.Namespace.RESERVED);
}

2.2 Zygote 接收请求并创建应用程序进程

Zygote 接收到请求并创建应用程序进程的时序图如下所示:

Zygote接收请求并创建应用程序进程

Socket 连接成功并匹配 ABI 之后会返回 ZygoteState 类型对象,在 ZygoteProcess.zygoteSendArgsAndGetResult 方法中,会将应用程序进程的启动参数写入到 ZygoteState 中,这样,Zygote 进程就会收到一个创建新的应用程序进程的请求。以下是 ZygoteInit.main 方法的代码:

// /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
    ZygoteServer zygoteServer = null;
    ...
    Runnable caller;
    try {
        if (!enableLazyPreload) {
            bootTimingsTraceLog.traceBegin("ZygotePreload");
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis());
            // 预加载类和资源
            preload(bootTimingsTraceLog); // 1
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis());
            bootTimingsTraceLog.traceEnd(); // ZygotePreload
        } else {
            Zygote.resetNicePriority();
        }
		
        // 创建一个 Server 端的 Socket
        zygoteServer = new ZygoteServer(isPrimaryZygote); // 2
        
        if (startSystemServer) {
            // 启动 system_server 进程
            Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer); // 3
            
            if (r != null) {
                r.run();
                return;
            }
        }

        Log.i(TAG, "Accepting command socket connections");
		// 等待 AMS 请求
        caller = zygoteServer.runSelectLoop(abiList); // 4
    }catch (Throwable ex) {
        Log.e(TAG, "System zygote died with exception", ex);
        throw ex;
    } finally {
        if (zygoteServer != null) {
            zygoteServer.closeServerSocket();
        }
    }

    if (caller != null) {
        caller.run();
    }
}

注释 1 处为预加载资源。注释 2 处创建了一个 Server 端的 Socket,这个 namezygoteSocket 用来等待 AMS 来请求 Zygote,以创建新的应用程序进程。注释 3 处为启动 system_server 进程,这样系统服务也就由 system_server 进程启动起来。在注释 4 处调用 ZygoteServer.runSelectLoop 方法来等待 AMS 请求创建新的应用程序进程。以下是 ZygoteServer.runSelectLoop 方法:

// /frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
Runnable runSelectLoop(String abiList) {
    ArrayList<FileDescriptor> socketFDs = new ArrayList<FileDescriptor>();
    ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>(); // 1

    socketFDs.add(mZygoteSocket.getFileDescriptor());
    peers.add(null);

    while (true) {
        ...
        while (--pollIndex >= 0) {
            if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
                continue;
            }

            if (pollIndex == 0) {
                // Zygote server socket
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                socketFDs.add(newPeer.getFileDescriptor());
            } else if (pollIndex < usapPoolEventFDIndex) {
                // Session socket accepted from the Zygote server socket
                try {
                    ZygoteConnection connection = peers.get(pollIndex);
                    final Runnable command = connection.processOneCommand(this); // 2

                    // TODO (chriswailes): Is this extra check necessary?
                    if (mIsForkChild) {
                        if (command == null) {
                            throw new IllegalStateException("command == null");
                        }

                        return command;
                    } else {
                        if (command != null) {
                            throw new IllegalStateException("command != null");
                        }
                        ...
                        if (connection.isClosedByPeer()) {
                            connection.closeSocket();
                            peers.remove(pollIndex);
                            socketFDs.remove(pollIndex);
                        }
                    }
                } catch (Exception e) {
                    ...
                } 
            }
            ...
        }
        ...
    }
}

当有 AMS 的请求数据到来时,会调用注释 2 处的代码,也就是 ZygoteConnection.processOneCommand 方法来处理请求数据的:

// /frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
Runnable processOneCommand(ZygoteServer zygoteServer) {
    String args[];
    ZygoteArguments parsedArgs = null;
    FileDescriptor[] descriptors;

    try {
        args = Zygote.readArgumentList(mSocketReader); // 1 获取应用程序进程的启动参数

        descriptors = mSocket.getAncillaryFileDescriptors();
    } catch (IOException ex) {
        throw new IllegalStateException("IOException on command socket", ex);
    }

  	...
    int pid = -1;
    ...

    parsedArgs = new ZygoteArguments(args); // 2

    ...
	// 3 创建应用程序进程
    pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,
                                   parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, 
                                   parsedArgs.mSeInfo, parsedArgs.mNiceName, fdsToClose, 
                                   fdsToIgnore, parsedArgs.mStartChildZygote,
                                   parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, 
                                   parsedArgs.mTargetSdkVersion);

    try {
        // 当前代码运行在子进程中
        if (pid == 0) {
            // in child
            zygoteServer.setForkChild();

            zygoteServer.closeServerSocket();
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;
			// 处理应用程序进程
            return handleChildProc(parsedArgs, descriptors, childPipeFd,
                                   parsedArgs.mStartChildZygote);
        } else {
            // In the parent. A pid < 0 indicates a failure and will be handled in
            // handleParentProc.
            IoUtils.closeQuietly(childPipeFd);
            childPipeFd = null;
            handleParentProc(pid, descriptors, serverPipeFd);
            return null;
        }
    } finally {
        IoUtils.closeQuietly(childPipeFd);
        IoUtils.closeQuietly(serverPipeFd);
    }
}

在注释 1 处调用 Zygote.readArgumentList 方法来获取应用程序进程的启动参数,并在注释 2 处将返回的字符串数组 args 封装到 ZygoteArguments 类型的 parsedArgs 对象中。在注释 3 处调用 Zygote.forkAndSpecialize 方法来创建应用程序进程,参数为 parsedArgs 中存储的应用进程启动参数,返回值为 pidZygote.forkAndSpecialize 方法主要是通过 fork 当前进程来创建一个子进程的,如果 pid == 0,则说明当前代码的逻辑运行在新创建的子进程(应用程序进程)中,这是就会调用 ZygoteConnection.handleChildProc 方法来处理应用程序进程, 代码如下所示:

// /frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor[] descriptors,
                                 FileDescriptor pipeFd, boolean isZygote) {
    
    closeSocket();
    ...
    // End of the postFork event.
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    if (parsedArgs.mInvokeWith != null) {
        WrapperInit.execApplication(parsedArgs.mInvokeWith,
                                    parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
                                    VMRuntime.getCurrentInstructionSet(),
                                    pipeFd, parsedArgs.mRemainingArgs);

        // Should not get here.
        throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");
    } else {
        if (!isZygote) {
            // 1
            return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                                         parsedArgs.mRemainingArgs, null /* classLoader */); 
        } else {
            return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
                                              parsedArgs.mRemainingArgs,
                                              null /* classLoader */);
        }
    }
}

ZygoteConnection.handleChildProc 方法中调用了 ZygoteInit.zygoteInit 方法,如下所示:

// /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,
                                        ClassLoader classLoader) {
    if (RuntimeInit.DEBUG) {
        Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
    }

    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
    RuntimeInit.redirectLogStreams();

    RuntimeInit.commonInit();
    ZygoteInit.nativeZygoteInit(); // 1
    return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader); // 2
}

在注释 1 处会在新创建的应用程序进程中创建 Binder 线程池(下面会做详细介绍),在注释 2 处调用了 RuntimeInit.applicationInit 方法:

// /frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
                                          ClassLoader classLoader) {
    ...
    final Arguments args = new Arguments(argv);

    // The end of of the RuntimeInit event (see #zygoteInit).
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

    // Remaining arguments are passed to the start class's static main
    return findStaticMain(args.startClass, args.startArgs, classLoader); // 1
}

RuntimeInit.applicationInit 方法会在注释 1 处调用 RuntimeInit.findStaticMain 方法,需要注意的是,第一个参数 arg.startClass,它指的就是 android.app.ActivityThread 接下来查看 RuntimeInit.findStaticMain 方法:

// /frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
protected static Runnable findStaticMain(String className, String[] argv, 
                                         ClassLoader classLoader) {
    Class<?> cl;

    try {
        cl = Class.forName(className, true, classLoader); // 1
    } 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 }); // 2
    } 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);
    }
   	...
    /*
     * This throw gets caught in ZygoteInit.main(), which responds
     * by invoking the exception's run() method. This arrangement
     * clears up all the stack frames that were required in setting
     * up the process.
     */
    return new MethodAndArgsCaller(m, argv); // 3
}

在注释 1 处通过反射获得了 android.app.ActivityThread 类,接下来在注释 2 处获得了 ActivityThrea.main 方法,并将 ActivityThread.main 方法传入注释 3 处的 RuntimeInit 中的 MethodAndArgsCaller 类:

// /frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
static class MethodAndArgsCaller implements Runnable {
    /** method to call */
    private final Method mMethod;

    /** argument array */
    private final String[] mArgs;

    public MethodAndArgsCaller(Method method, String[] args) {
        mMethod = method;
        mArgs = args;
    }

    public void run() {
        try {
            mMethod.invoke(null, new Object[] { mArgs }); // 1
        } 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);
        }
    }
}

注释 1 处的 mMethod 指的是 ActivityThread.main 方法,调用了 mMethod.invoke 方法后,ActivityThread.maim 方法就会被动态调用了,应用程序进程就进入了 ActivityThread.main 方法中。

ZygoteInit.main 方法中调用 MethodAndArgsCaller.run 方法:

// /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
    ...
    Runnable caller;
    ...
    caller = zygoteServer.runSelectLoop(abiList); 
    ... 
    if (caller != null) {
        caller.run();
    }
}

3 Binder 线程池启动过程

ZygoteInit.zygoteInit 方法中会启动 Binder 线程池:

// /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,
                                        ClassLoader classLoader) {
    if (RuntimeInit.DEBUG) {
        Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
    }

    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
    RuntimeInit.redirectLogStreams();

    RuntimeInit.commonInit();
    ZygoteInit.nativeZygoteInit(); // 1
    return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}

private static final native void nativeZygoteInit(); // 2

nativeZygoteInit 方法是一个 JNI 方法,它对应的是 AndroidRuntime.cppJNINativeMethod 数组中的 register_com_android_internal_os_ZygoteInit_nativeZygoteInit,对应的函数是 com_android_internal_os_ZygoteInit_nativeZygoteInit

// /frameworks/base/core/jni/AndroidRuntime.cpp
static const RegJNIRec gRegJNI[] = {
    ...
    REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),
    ...
}

int register_com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env)
{
    const JNINativeMethod methods[] = {
        { "nativeZygoteInit", "()V",
         (void*) com_android_internal_os_ZygoteInit_nativeZygoteInit },
    };
    return jniRegisterNativeMethods(env, "com/android/internal/os/ZygoteInit",
                                    methods, NELEM(methods));
}

static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit(); // 1
}

gCurRuntimeAndroidRuntime 类型的指针,它是在 AndroidRuntime 初始化的时候创建的:

// /frameworks/base/core/jni/AndroidRuntime.cpp
static AndroidRuntime* gCurRuntime = NULL;

AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength) :
		mExitWithoutCleanup(false),
		mArgBlockStart(argBlockStart),
		mArgBlockLength(argBlockLength)
{
    SkGraphics::Init();

    // Pre-allocate enough space to hold a fair number of options.
    mOptions.setCapacity(20);

    assert(gCurRuntime == NULL);        // one per process
    gCurRuntime = this;
}

AppRuntiem 继承自 AndroidRuntimeAppRuntime 创建时会调用 AndroidRuntime 的构造函数,gCurRuntime 就会被初始化,它指向的是 AppRuntime。接下来查看 AppRuntime.onZygoteInit 函数,AppRuntimeapp_main.cpp 中实现:

// /frameworks/base/cmds/app_process/app_main.cpp
class AppRuntime : public AndroidRuntime
{
    virtual void onZygoteInit()
    {
        sp<ProcessState> proc = ProcessState::self();
        ALOGV("App process: starting thread pool.\n");
        proc->startThreadPool();// 1
    }
}

注释 1 处调用了 ProcessState.startThreadPool 函数来启动 Binder 线程池:

// /frameworks/native/libs/binder/ProcessState.cpp
void ProcessState::startThreadPool()
{
    AutoMutex _l(mLock);
    if (!mThreadPoolStarted) { // 1
        mThreadPoolStarted = true; // 2
        spawnPooledThread(true);
    }
}

支持 Binder 通信的进程中都有一个 ProcessState 类,它里面有一个 mThreadPoolStarted 变量,用来表示 Binder 线程池是否已经被启动过,默认值是 false,在每次调用 startThreadPool 函数时都会在注释 1 处先检查这个标记,从而确保 Binder 线程池只会启动一次。如果 Binder 线程池未被启动,则在注释 2 处设置 mThreadPoolStarted = true,并调用 spawnPooledThread 函数来创建线程池中的第一个线程,也就是线程池的主线程:

// /frameworks/native/libs/binder/ProcessState.cpp
void ProcessState::spawnPooledThread(bool isMain)
{
    if (mThreadPoolStarted) {
        String8 name = makeBinderThreadName();
        ALOGV("Spawning new pooled thread, name=%s\n", name.string());
        sp<Thread> t = new PoolThread(isMain);
        t->run(name.string()); // 1
    }
}

可以看到 Binder 线程为一个 PoolThread。在注释 1 调用 PoolThread.run 函数来启动一个新的线程,下面是 PoolThread 的相关代码:

// /frameworks/native/libs/binder/ProcessState.cpp
class PoolThread : public Thread
{
    public:
    explicit PoolThread(bool isMain)
        : mIsMain(isMain)
        {
        }

    protected:
    virtual bool threadLoop()
    {
        IPCThreadState::self()->joinThreadPool(mIsMain); // 1
        return false;
    }

    const bool mIsMain;
}; 

PoolThread 继承了 Thread 类,在注释 1 处调用了 IPCThreadStatejoinThreadPool 函数,将当前线程注册到 Binder 驱动中,这样创建的线程就加入了 Binder 线程池中,这样,新创建的应用程序进程就支持 Binder 进程间通信。 我们只需要创建当前进程的 Binder 对象,并将它注册到 ServiceManager 中就可以实现 Binder 进程间通信,而不必关系进程间是如何通过 Binder 进行通信的。

4 消息循环创建过程

通过上面的介绍可以知道,在 ZygoteInit.main 中调用 caller.run ,会执行 MethodAndArgsCaller.run 方法:

// /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
    ...
    Runnable caller;
    ...
    caller = zygoteServer.runSelectLoop(abiList); 
    ... 
    if (caller != null) {
        caller.run();
    }
}

以下是 MethodAndArgsCaller 的相关源码:

// /frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
static class MethodAndArgsCaller implements Runnable {
    /** method to call */
    private final Method mMethod;

    /** argument array */
    private final String[] mArgs;

    public MethodAndArgsCaller(Method method, String[] args) {
        mMethod = method;
        mArgs = args;
    }

    public void run() {
        try {
            mMethod.invoke(null, new Object[] { mArgs }); // 1
        } 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);
        }
    }
}

而注释 1 处的 mMethod 指的是 ActivityThread.main 方法,以下是 ActivityThread.main 的相关源码:

// /frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
    ...
    Looper.prepareMainLooper(); // 1 创建主线程 Looper
    ActivityThread thread = new ActivityThread(); // 2
    thread.attach(false, startSeq);

    if (sMainThreadHandler == null) { // 3
        sMainThreadHandler = thread.getHandler(); // 4 创建主线程的 H 类
    }

    if (false) {
        Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread"));
    }

    // End of event ActivityThreadMain.
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    Looper.loop(); // 5 Looper 开始工作
}

ActivityThread 类用于管理当前应用程序进程的主线程,在注释 1 处创建主线程的消息循环 Looper,在注释 2 处创建 ActivityThread。在注释 3 出判断 Handler 类型的 sMainThreadHandler 是否为 null,如果为 null 则在注释 4 出获取 H 类并赋值给 sMainThreadHandler,这个 H 继承自 Handler,是 ActivityThread 的内部类,用户处理主线程的消息循环。注释 5 处调用 Looper.loop 方法,使得 Looper 开始处理消息。

可以看出,系统在应用程序进程启动完成后,会创建一个消息循环,这样运行在应用程序进程中的应用程序就可以方便的使用消息处理机制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/168935.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023牛客寒假算法基础集训营1--鸡玩炸蛋人(带权并查集) 诈骗题?

题目如下&#xff1a; 示例1 输入 6 4 1 2 2 3 1 3 4 6 0 0 0 0 0 0输出 14示例2 输入 6 4 1 2 2 3 1 3 4 6 0 0 0 0 2 0输出 1题目链接 题解 or 思路&#xff1a; 首先如果我们理解题意了&#xff0c;这个题是顶级诈骗。 因为是无向图&#xff0c;我们需要记录图中 环…

算法第十三期——BFS-双向广搜

双向广搜 应用场景&#xff1a;有确定的起点s和终点t&#xff1b;把从起点到终点的单向搜索&#xff0c;变换为分别从起点出发和从终点出发的“相遇”问题。操作&#xff1a;从起点s(正向搜索&#xff09;和终点t(逆向搜索&#xff09;同时开始搜索&#xff0c;当两个搜索产生…

编程太难不适合女生学?来看 N 多小姐姐的回应!

某女程序员&#xff1a;我要去互联网公司做程序员&#xff1f;网友&#xff1a;你疯了&#xff1f;程序员很累的... 女生不适合做程序员&#xff0c;还是去做产品经理吧。画外音&#xff1a;我去&#xff0c;产品经理不累吗&#xff1f;并不是女生不适合写代码&#xff0c;也不…

python cairosvg 库专题博客,10分钟掌握 cairosvg

cairosvg 库用于将 SVG 图像转换为其他图片格式。它使用 Cairo 库来绘制 SVG 图像&#xff0c;并支持将 SVG 图像转换为 PNG、PDF、PS、SVG 和 GIF 格式。 python cairosvgPython cairosvg 上手案例cairosvg 直接将 svg 图像转换为二进制数据cairosvg 库函数清单总结Python cai…

趣味三角——第1章——角

平面角是平面内相交但不在一条直线上的两条直线之间的倾角(A plane angle is the inclination to one another of two lines in a plane which meet one another and do not lie in a straight line.)。 ——Euclid(欧几里得), 元素(The Elements)&#xff0c;定义8。 几何实体…

【C++】Hash开散列,unordered_set(map) 的封装以及迭代器的实现

上一篇博客我们使用闭散列的方式实现了 Hash&#xff0c;其实在STL库unordered_set、unordered_map中底层是开散列的方式实现的Hash&#xff0c;所以&#xff0c;本篇博客就再使用开散列的方式实现Hash&#xff0c;并将unordered_set、unordered_map进行封装。 目录 一、开散…

C 数据结构1 —— 线性表-顺序表\单链表\双链表

文章目录1. 线性表1.1 定义1.2 特点2. 顺序表(顺序存储结构)2.1 定义(存储结构代码描述)2.2 插入元素2.2.1 图形演示2.2.2 代码表示2.3 删除元素2.3.1 图形演示2.3.2 代码表示2.4 完整代码2.5 动态分配数组3. 单链表(链式存储结构)3.1 定义(存储结构代码描述)3.2 单链表的读取3…

COCO_04 展示COCO格式数据集 目标框与分割mask

文章目录1 前言2 绘制GT2.1 绘制目标框与类别2.2 绘制分割mask3 AppendixA. mask polygon格式转化为图片格式参考1 前言 上篇文章介绍了如何制作COCO个数数据集的Dataset与Dataloader&#xff0c;并绘制了dataloader->batch的返回的信息&#xff0c;https://blog.csdn.net/…

【打卡】医学搜索Query相关性判断学习赛

入坑传送门 赛事介绍 文本匹配拥有广泛的应用场景&#xff0c;可以用于去除重复问题和文本相似度中。在本次学习中我们将学习&#xff1a; 如何计算文本之间的统计距离如何训练词向量 & 无监督句子编码BERT模型搭建和训练 上述步骤都是一个NLP算法工程师必备的基础&…

【GD32F427开发板试用】02-ADC规则组连续采样

本篇文章来自极术社区与兆易创新组织的GD32F427开发板评测活动&#xff0c;更多开发板试用活动请关注极术社区网站。作者&#xff1a;Stark_GS ADC 简介及特点 器件中集成了一个 12 位 2.6 MSPS 多通道 ADC。 一共有19个多路复用通道&#xff1a;16个外部通道&#xff0c;1个…

office365删除错误发送的邮件

微软喜欢变&#xff0c;office365删个邮件真是不容易。 --管理员登录 Connect-IPPSSession -UserPrincipalName adminmydomain.onmicrosoft.com --创建一个 "deleteemail"的搜索项目&#xff0c;项目名可以任意起&#xff0c;这个名称后面在office365安全合规门户里…

libcurl简介及其编程应用

本文为学习笔记&#xff0c;整合课程内容以及下列文章&#xff1a; 其中&#xff0c;libcurl函数库常用字段解读部分&#xff1a; 参考博文&#xff1a;原文地址 作者&#xff1a;冬冬他哥哥 目录 libcurl简介 libcurl的使用 学会开源包使用的一般步骤 包的解读 重点是看…

Spark 核心编程

文章目录Spark 核心编程一、RDD1、分布式计算模拟(1) 搭建基础的架子(2) 客户端向服务器发送计算任务Spark 核心编程 Spark 计算框架为了能够进行高并发和高吞吐的数据处理&#xff0c;封装了三大数据结构&#xff0c;用于处理不同的应用场景。三大数据结构分别是&#xff1a;…

【数据结构与算法理论知识点】1.1基本概念

1.1基本概念 为什么要学习数据结构与算法&#xff1f; AlgorithmsData StructuresPrograms---- Niklaus Wirth ( Pascal程序设计语言之父、结构化程序设计首创者、图灵奖获得者) 计算机程序&#xff1a;使用计算机求解问题算法是求解问题的步骤的描述&#xff1a;从蛮力到策…

套接字编程(二)UDP服务端与客户端的通信模拟实现

目录 一、前言 二、UDP客户端流程信息 1、创建套接字 2、为套接字绑定地址信息&#xff08;不推荐&#xff09; 3、发送数据&#xff08;将数据放入发送缓冲区中&#xff09; 4、接收数据&#xff08;从socket结构体接收缓冲区中取出数据&#xff09; 5、关闭套接字 三…

机器学习基本概念及问题梳理

前言&#xff1a;整理西瓜书第一、二章中的基本概念 待办&#xff1a;第二章评估方法、性能度量及后续内容未整理 下图梳理机器学习中部分概念 模型评估与选择相关知识点&#xff1a; 错误率&#xff08;error rate, E&#xff09;&#xff1a;如果在m个样本中有a个样本分类…

WordPress安全指南:19个步骤让您的WordPress安全防线坚如磐石

谈到WordPress安全性&#xff0c;您可以采取很多措施来锁定您的网站&#xff0c;以防止黑客和漏洞影响您的电子商务网站或博客。您最不想发生的事情是一天早上醒来发现您的网站一团糟。因此&#xff0c;今天我们将分享许多技巧、策略和技术&#xff0c;您可以使用这些技巧、策略…

WEBSHELL管理工具流量特征——基础篇

前言 前一阵子帮别人做取证题目&#xff0c;有很多关于WEBSHELL的流量要分析&#xff0c;想起来还有没好好分析过于是准备写篇文章总结一下帮助大家能够快速的辨别WEBSHELL流量&#xff0c;下面我们展开文章来讲。 中国菜刀 这个应该是大家最熟悉的WEBSHELL管理工具&#xf…

NeuRay学习笔记

Neural Rays for Occlusion-aware Image-based Rendering 主页&#xff1a;https://liuyuan-pal.github.io/NeuRay/ 论文&#xff1a;https://arxiv.org/abs/2107.13421 Code&#xff1a;https://github.com/liuyuan-pal/NeuRay 效果&#xff1a; desktop摘要 We present a ne…

一文读懂 UniProt 数据库(2023 最新版)

一、UniProt 数据库介绍 Uniprot &#xff08;Universal Protein &#xff09;是包含蛋白质序列&#xff0c;功能信息&#xff0c;研究论文索引的蛋白质数据库&#xff0c;整合了包括EBI&#xff08; European Bioinformatics Institute&#xff09;&#xff0c;SIB&#xff0…