Android應(yīng)用進(jìn)程的創(chuàng)建姿勢

Android應(yīng)用進(jìn)程的創(chuàng)建

在之前的Android啟動流程中,我們最后提到了會通過ActivityManagerServicestartProcess方法來進(jìn)行應(yīng)用進(jìn)程的創(chuàng)建。本篇文章我們就從這里開始著手,來進(jìn)行相關(guān)源碼的解析工作。

ActivityManagerService#startProcess

    //ActivityManagerService#LocalService.java
    public void startProcess(String processName, ApplicationInfo info,
            boolean knownToBeDead, String hostingType, ComponentName hostingName) {
        try {
            //同步操作,避免死鎖
            synchronized (ActivityManagerService.this) {
                //調(diào)用startProcessLocked方法, Process的start,最終到ZygoteProcess的attemptUsapSendArgsAndGetResult()
                // 用來fork一個新的Launcher的進(jìn)程
                startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,new HostingRecord(hostingType, hostingName),false /* allowWhileBooting */, false /* isolated */,true /* keepIfLarge */);
            }
        ...
    }
    
    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 */);
    }

這里最終調(diào)用了ProcessList的startProcessLocked方法。這里的ProcessList類的主要作用是用來處理進(jìn)程。

ProcessList#startProcessLocked

    //啟動進(jìn)程
    @GuardedBy("mService")
    boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
            boolean disableHiddenApiChecks, boolean mountExtStorageFull,
            String abiOverride) {
        //已經(jīng)啟動,則直接返回
        if (app.pendingStart) {
            return true;
        }
        //啟動時間
        long startTime = SystemClock.elapsedRealtime();
        ...
            //設(shè)置程序的入口
            final String entryPoint = "android.app.ActivityThread";
            //***重點方法****
            return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
                    runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,
                    startTime);
       ...
    }

調(diào)用了一個重載方法,注意我們這里的一個參數(shù)entryPoint,這個是我們的進(jìn)程啟動以后的入口類,當(dāng)我們fork出進(jìn)程以后,會調(diào)用這個類中的main方法來啟進(jìn)程。

    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(app.hostingRecord,
                            entryPoint, app, app.startUid, gids, runtimeFlags, mountExternal,
                            app.seInfo, requiredAbi, instructionSet, invokeWith, app.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) {
                //*****重點方法*****最終調(diào)用的創(chuàng)建進(jìn)程的方法
                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});
    }

最后將進(jìn)程的創(chuàng)建交給Process類來進(jìn)行處理,通過start方法創(chuàng)建,然后返回了ProcessStartResult啟動的結(jié)果。

Process#start

    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) {
        //processClass為"android.app.ActivityThread",表示程序的入口類
        return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, packageName,
                    /*useUsapPool=*/ true, zygoteArgs);
    }

調(diào)用ZygoteProcess的start方法

ZygoteProcess#start

    //啟動一個新的進(jìn)程
    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) {
        try {
            //***重點方法****
            return startViaZygote(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,
                    packageName, useUsapPool, zygoteArgs);
        }
        ...
    }

    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 {
        ArrayList<String> argsForZygote = new ArrayList<>();
        //這是一些創(chuàng)建進(jìn)程時候的參數(shù)信息
        ...
        //這個是程序的入口類,設(shè)置的是"android.app.ActivityThread"
        argsForZygote.add(processClass);
        ...
        synchronized(mLock) {
            //***重點方法***
            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
                                              useUsapPool,
                                              argsForZygote);
        }
    }


openZygoteSocketIfNeeded 會創(chuàng)建一個和Zygote的socket連接。

    //如果初始的Zygote的連接不存在或者未連接。則創(chuàng)建一個Socket連接,并將相關(guān)信息封裝為ZygoteState
    @GuardedBy("mLock")
    private void attemptConnectionToPrimaryZygote() throws IOException {
        //如果沒有連接
        if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
            primaryZygoteState = ZygoteState.connect(mZygoteSocketAddress, mUsapPoolSocketAddress);
        }
    }

如果之前沒有建立過和Zygote之間的連接,那么會通過connect()方法進(jìn)行連接

        static ZygoteState connect(@NonNull LocalSocketAddress zygoteSocketAddress,@Nullable LocalSocketAddress usapSocketAddress)throws IOException {
            DataInputStream zygoteInputStream;
            BufferedWriter zygoteOutputWriter;
            final LocalSocket zygoteSessionSocket = new LocalSocket();
            try {
                //進(jìn)行連接
                zygoteSessionSocket.connect(zygoteSocketAddress);
                //創(chuàng)建DataInputStream
                zygoteInputStream = new DataInputStream(zygoteSessionSocket.getInputStream());
                //創(chuàng)建BufferedWriter
                zygoteOutputWriter = new BufferedWriter(new OutputStreamWriter(zygoteSessionSocket.getOutputStream()),Zygote.SOCKET_BUFFER_SIZE);
            ...
            //封裝為ZygoteState對象
            return new ZygoteState(zygoteSocketAddress, usapSocketAddress,
                                   zygoteSessionSocket, zygoteInputStream, zygoteOutputWriter,
                                   getAbiList(zygoteOutputWriter, zygoteInputStream));
        }

所以openZygoteSocketIfNeeded的主要作用是保證和Zygote的socket連接的存在。當(dāng)連接存在以后就可以通過socket進(jìn)行消息的傳輸了。

ZygoteProcess#zygoteSendArgsAndGetResult

通過socket連接Zygote,并發(fā)送對應(yīng)的fork進(jìn)程所需要的信息

    private Process.ProcessStartResult zygoteSendArgsAndGetResult(
            ZygoteState zygoteState, boolean useUsapPool, @NonNull ArrayList<String> args) throws ZygoteStartFailedEx {
        //****重點方法**** 嘗試fork子線程
        return attemptZygoteSendArgsAndGetResult(zygoteState, msgStr);
    }   
    
    private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult(
            ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx {
        try {
            //傳入的zygoteState為openZygoteSocketIfNeeded(),里面會通過abi來檢查是第一個zygote還是第二個
            final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter;
            final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;
            //將參數(shù)的信息寫給Zygote進(jìn)程,包括前面的processClass ="android.app.ActivityThread"
            zygoteWriter.write(msgStr);
            //刷數(shù)據(jù),全部寫入Zygote進(jìn)程,處于阻塞狀態(tài)
            zygoteWriter.flush();
            //從socket中得到zygote創(chuàng)建的應(yīng)用pid,賦值給 ProcessStartResult的對象
            Process.ProcessStartResult result = new Process.ProcessStartResult();
            //從socket中讀取創(chuàng)建的進(jìn)程的pid
            result.pid = zygoteInputStream.readInt();
            result.usingWrapper = zygoteInputStream.readBoolean();
            //如果pid<0,表示創(chuàng)建失敗
            if (result.pid < 0) {
                throw new ZygoteStartFailedEx("fork() failed");
            }
            return result;
        } 
        ...
    }

最后會通過socket連接到Zygote進(jìn)程,將對應(yīng)的參數(shù)發(fā)送給Socket的Server端以后,由Server端來進(jìn)行進(jìn)程的fork操作,操作完成以后將創(chuàng)建的進(jìn)程id返回。

那么Zygote的Server端又是如何創(chuàng)建的呢?

Zygote啟動監(jiān)聽

這個就涉及了Zygote的啟動過程了。這部分我們后續(xù)可以詳細(xì)分析,這里只提一下大體的流程。

Zygote會先fork出SystemServer進(jìn)程,然后會進(jìn)入循環(huán)等待,用來接收Socket發(fā)來的消息,用來fork出其他應(yīng)用所需要的進(jìn)程信息。

    //ZygoteInit.java
    public static void main(String argv[]) {
        ZygoteServer zygoteServer = null;
        Runnable caller;
        try {
            //創(chuàng)建一個ZygoteServer對象,這個對象創(chuàng)建一個socket服務(wù)端,能夠接收連接并且孵化對應(yīng)的子進(jìn)程
            zygoteServer = new ZygoteServer(isPrimaryZygote);
            if (startSystemServer) {
                //Fork出第一個進(jìn)程  SystemServer服務(wù)所需的進(jìn)程
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
                if (r != null) {
                    //啟動SystemServer服務(wù)
                    r.run();
                    return;
                }
            }
            //***重點方法***   這里會進(jìn)入循環(huán)等待,用來接收Socket發(fā)來的消息,用來fork出其他應(yīng)用所需要的進(jìn)程信息。并且返回fork出的進(jìn)程的啟動函數(shù)
            caller = zygoteServer.runSelectLoop(abiList);
        ....
        if (caller != null) {
            //調(diào)用caller的run方法,啟動子進(jìn)程(run方法會調(diào)用子進(jìn)程的啟動程序的main方法,也就是ActivityThread.java的main()方法)
            caller.run();
        }
    }

連接的處理

我們這里看一下runSelectLoop這個方法如何監(jiān)聽Socket連接以及接收消息的

    Runnable runSelectLoop(String abiList) {
        ArrayList<FileDescriptor> socketFDs = new ArrayList<FileDescriptor>();
        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
        //socketFDs[0]是socketServer。
        socketFDs.add(mZygoteSocket.getFileDescriptor());
        peers.add(null);
        //死循環(huán)
        while (true) {
            {
                //這里會進(jìn)入阻塞,當(dāng)有pollFDs事件到來的時候,則繼續(xù)往下執(zhí)行
                Os.poll(pollFDs, -1);
            } catch (ErrnoException ex) {
                throw new RuntimeException("poll failed", ex);
            }
            while (--pollIndex >= 0) {
                if (pollIndex == 0) {
                    //采用I/O 多路復(fù)用機制,index==0表示selcet接收到的是Zygote的socket連接的事件.
                    // 客戶端第一次請求服務(wù)端,服務(wù)端會調(diào)用accept方法與客戶端建立連接,客戶端在zygote以ZygoteConnection對象表示
                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
                    peers.add(newPeer);
                    socketFDs.add(newPeer.getFileDescriptor());
                } else if (pollIndex < usapPoolEventFDIndex) {
                    //當(dāng)連接以后,能夠接收指令,這里根據(jù)
                    try {
                        //peers.get(index)取得發(fā)送數(shù)據(jù)客戶端的ZygoteConnection對象。這個就是多路復(fù)用的機制了
                        ZygoteConnection connection = peers.get(pollIndex);
                        //收到Socket發(fā)來的消息,進(jìn)行fork的創(chuàng)建工作。返回的command是MethodAndArgsCaller類
                        //其run方法,會調(diào)用通過socket接收到的啟動類的main方法
                        final Runnable command = connection.processOneCommand(this);
                        ....
    }

當(dāng)啟動循環(huán)以后,會一直遍歷等待,等待接收Socket發(fā)來的連接以及消息請求。當(dāng)獲取到對應(yīng)的客戶端的ZygoteConnection對象以后,這里會調(diào)用processOneCommand指令來進(jìn)行處理。

到這里的話,就可以和我們剛才講的創(chuàng)建Socket連接關(guān)聯(lián)起來了。

我們看一下processOneCommand這個方法是如何對發(fā)送的相關(guān)fork進(jìn)程的參數(shù)來進(jìn)行處理的。

    Runnable processOneCommand(ZygoteServer zygoteServer) {
        String args[];
        ZygoteArguments parsedArgs = null;
        FileDescriptor[] descriptors;
        try {
            //讀取socket傳來的參數(shù)信息
            args = Zygote.readArgumentList(mSocketReader);
        ...
        parsedArgs = new ZygoteArguments(args);
        fd = null;
        //*****重點方法**** fork一個子進(jìn)程,得到一個對應(yīng)的進(jìn)程pid
        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) {
                //當(dāng)pid=0,說明是fork的子進(jìn)程
                zygoteServer.setForkChild();
                zygoteServer.closeServerSocket();
                IoUtils.closeQuietly(serverPipeFd);
                serverPipeFd = null;
                //****重點方法*****  處理子進(jìn)程
                return handleChildProc(parsedArgs, descriptors, childPipeFd,
                        parsedArgs.mStartChildZygote);
        ...
    }

我們將這個方法分為3個大內(nèi)容來處理

  1. 將接收到的數(shù)據(jù)進(jìn)行解析處理,生成ZygoteArguments對象,這個對象里面包含了我們設(shè)置的進(jìn)程創(chuàng)建以后的入口類(即啟動類)
  2. 通過forkAndSpecialize方法fork出一個子進(jìn)程
  3. 通過handleChildProc方法對fork出的子進(jìn)程進(jìn)行處理

我們分別對上面的3部分進(jìn)行分析:

參數(shù)的解析

這里接收的參數(shù),是在我們的socket的client端來進(jìn)行創(chuàng)建的。

//ZygoteProcess.java #startViaZygote方法
        ArrayList<String> argsForZygote = new ArrayList<>();
        // --runtime-args, --setuid=, --setgid=,
        // and --setgroups= must go first
        //這是一些創(chuàng)建進(jìn)程時候的參數(shù)信息
        argsForZygote.add("--runtime-args");
        argsForZygote.add("--setuid=" + uid);
        argsForZygote.add("--setgid=" + gid);
        argsForZygote.add("--runtime-flags=" + runtimeFlags);
        if (mountExternal == Zygote.MOUNT_EXTERNAL_DEFAULT) {
            argsForZygote.add("--mount-external-default");
        } else if (mountExternal == Zygote.MOUNT_EXTERNAL_READ) {
            argsForZygote.add("--mount-external-read");
        } else if (mountExternal == Zygote.MOUNT_EXTERNAL_WRITE) {
            argsForZygote.add("--mount-external-write");
        } else if (mountExternal == Zygote.MOUNT_EXTERNAL_FULL) {
            argsForZygote.add("--mount-external-full");
        } else if (mountExternal == Zygote.MOUNT_EXTERNAL_INSTALLER) {
            argsForZygote.add("--mount-external-installer");
        } else if (mountExternal == Zygote.MOUNT_EXTERNAL_LEGACY) {
            argsForZygote.add("--mount-external-legacy");
        }

        argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
        argsForZygote.add(processClass);
        
        //ZygoteProcess.java # zygoteSendArgsAndGetResult方法
        String msgStr = args.size() + "\n" + String.join("\n", args) + "\n";

這里的參數(shù)的樣式是"--setuid=1",行與行之間以"\r"、"\n"或者"\r\n"分割,最后一個參數(shù)是進(jìn)程的入口類。在解析的時候,會按照格式進(jìn)行拆分。

子進(jìn)程的創(chuàng)建

對于子進(jìn)程的fork,是通過Zygote.forkAndSpecialize來處理的。

    //Zygote.java
    //fork一個子進(jìn)程,如果這是子節(jié)點則返回0;如果這是父進(jìn)程,則返回子進(jìn)程的pid;發(fā)生異常則返回-1。
    public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
            int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
            int targetSdkVersion) {
        ...
        //調(diào)用native方法,fork出一個子進(jìn)程。具體的位置在com_android_internal_os_Zygote.cpp
        int pid = nativeForkAndSpecialize(uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,fdsToIgnore, startChildZygote, instructionSet, appDataDir);
        ...
        return pid;
    }

這里調(diào)用了一個native方法來進(jìn)行線程的fork操作。由于采用copy on write方式,這里執(zhí)行一次,會返回兩次。

創(chuàng)建結(jié)果的處理

當(dāng)通過native進(jìn)行了子進(jìn)程的fork操作以后,會返回pid。這里的pid根據(jù)具體的值表示的是不同的類型

  • pid=0:表示處于子進(jìn)程
  • pid>0:表示處于Zygote進(jìn)程
  • pid<0:表示子進(jìn)程的創(chuàng)建失敗

這里我們只關(guān)心子進(jìn)程的處理。也就是handleChildProc方法。

    //ZygoteConnection.java
    //進(jìn)程創(chuàng)建完成后的處理工作,適當(dāng)?shù)年P(guān)閉socket,適當(dāng)?shù)闹匦麓蜷_stdio,返回成功或者失敗信息等
    //返回的Runnable是一個封裝了創(chuàng)建進(jìn)程時,socket傳進(jìn)來的程序入口的方法以及對應(yīng)的參數(shù)的類。其run方法會通過反射調(diào)用類的main方法
    private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor[] descriptors,FileDescriptor pipeFd, boolean isZygote) {
 
        //當(dāng)執(zhí)行到這的時候,connection已經(jīng)關(guān)閉了關(guān)閉socket,用/dev/null替換它們。
        closeSocket();
        ...
                //這個里面會通過反射創(chuàng)建socket傳遞的啟動程序的入口類(ActivityThread),然后調(diào)用其main方法進(jìn)行啟動
                return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
                        parsedArgs.mRemainingArgs, null /* classLoader */);
            }
        }
    }

這個方法在最后會調(diào)用childZygoteInit方法,然后返回一個Runnable對象。

    static final Runnable childZygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
        //根據(jù)argv獲取到對應(yīng)的運行的相關(guān)參數(shù)
        RuntimeInit.Arguments args = new RuntimeInit.Arguments(argv);
        return RuntimeInit.findStaticMain(args.startClass, args.startArgs, classLoader);
    }

這里根據(jù)解析后的參數(shù)信息,生成了Arguments對象。

        //RuntimeInit.java
        Arguments(String args[]) throws IllegalArgumentException {
            parseArgs(args);
        }
        
        //進(jìn)行參數(shù)的解析
        private void parseArgs(String args[]) throws IllegalArgumentException {
            int curArg = 0;
            for (; curArg < args.length; curArg++) {
                String arg = args[curArg];
                if (arg.equals("--")) {
                    curArg++;
                    break;
                } else if (!arg.startsWith("--")) {
                    break;
                }
            }
            //在傳遞參數(shù)的時候,最后一項傳遞的是程序入口類的信息
            startClass = args[curArg++];
            //參數(shù)信息
            startArgs = new String[args.length - curArg];
            System.arraycopy(args, curArg, startArgs, 0, startArgs.length);
        }
    }

方法中會根據(jù)傳入的參數(shù)確定了fork的子進(jìn)程啟動時的類startClass以及對應(yīng)的參數(shù)startArgs。

     //ZygoteInit.java
    //調(diào)用傳入的className所對應(yīng)的類的main方法
    protected static Runnable findStaticMain(String className, String[] argv, ClassLoader classLoader) {
         Class<?> cl;
         //反射創(chuàng)建類
         cl = Class.forName(className, true, classLoader);
         Method m;
        //獲取類的main方法
          m = cl.getMethod("main", new Class[] { String[].class });
         //封裝一個Runnable類,將方法和參數(shù)都傳遞給了該類,其run方法會通過反射調(diào)用main方法
         return new MethodAndArgsCaller(m, argv);
    }

   static class MethodAndArgsCaller implements Runnable {
        //調(diào)用的方法
        private final Method mMethod;
        //方法的參數(shù)
        private final String[] mArgs;

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

        public void run() {
            try {
                mMethod.invoke(null, new Object[] { mArgs });
            } 
            ...
        }
    }

handleChildProc會根據(jù)將傳入的參數(shù)信息,返回子進(jìn)程啟動時所使用的方法通過反射獲取到,并放在一個Runnable的run方法中去執(zhí)行。

那么這個Runnable的啟動是在哪兒呢?

//ZygoteInit.java
    public static void main(String argv[]) {
        ...
           caller = zygoteServer.runSelectLoop(abiList);
        ...
        if (caller != null) {
            //調(diào)用caller的run方法,啟動子進(jìn)程(run方法會調(diào)用子進(jìn)程的啟動程序的main方法,也就是ActivityThread.java的main()方法)
            caller.run();
        }

當(dāng)通過runSelectLoop方法fork完對應(yīng)的子進(jìn)程以后,會將這個MethodAndArgsCaller返回并執(zhí)行。我們一開始傳入的ActivityThread的main方法就調(diào)用并執(zhí)行了。

總結(jié)

  1. 在fork子進(jìn)程之后,直接執(zhí)行了ActivityThread的main方法來啟動的。
  2. 在系統(tǒng)啟動時,開啟了Zygote的Socket的Server端來監(jiān)聽,當(dāng)需要創(chuàng)建進(jìn)程時,直接通過Socket連接,然后傳遞參數(shù)來創(chuàng)建。
  3. fork采用了copy on write方式。
  4. Server端對于連接的處理,采用了I/O 多路復(fù)用機制。具體的這個機制,這個機制回頭可以延伸一下。

源碼解析項目地址

本文由 開了肯 發(fā)布!

同步公眾號[開了肯]

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容