Android进程系列第五篇---应用进程的创建流程

一、内容预览

应用进程的创建.png

二、概述

前面进程系列已经更新了四篇,本文(基于Android O源码),梳理应用进程的创建流程。
进程系列第一篇---进程基础
进程系列第二篇---Zygote进程的创建流程
Android进程第三篇---SystemServer进程创建流程
Android进程第四篇---SystemServer进程的启动流程

下面是一个进程创建架构图,可以了解一个进程创建的大概流程。


应用进程创建架构图.png

一共涉及了几个角色,发起进程、System进程、Zygote进程、新进程

  • 发起进程
    一个App进程可以通过startActivity等系统API请求SystemServer进程创建进程,SystemServer进程把这个活交给了Process.start,这个就是创建进程的入口。

  • System进程
    紧接着SystemServer进程通知ZygoteState创建LocalSocket,此时,SystemServer进程一直扮演的都是客户端的角色。

  • Zygote进程
    另一方面,在Android开机的过程中,Zygote进程就已经早早的启动了,所以LocalServerSocket就已经很早创建了,runSelectLoop开启了一个死循环一直accept客户端的连接,当SystemServer进程把LocalSocket创建出来之后,就可以使用LocalSocket send/recv数据了,此时就可以通知LocalServerSocket我要创建一个进程。进程fork完成之后,返回结果给System进程的AMS。

  • 新进程
    Zygote进程把进程fork出来之后,需要做进程的初始化操作,比如设置进程异常的捕获方式,开始Binder线程池等等,最后进入了ActivityThread的main方法,一个有血有肉的进程正式被启动了。

三、进程的创建流程

3.1、发送创建请求,从Process类的start方法开始

所有进程创建的请求都交给Process,从Process类的start方法开始。

frameworks/base/core/java/android/os/Process.java
/**
    * Start a new process.
    * 
    * <p>If processes are enabled, a new process is created and the
    * static main() function of a <var>processClass</var> is executed there.
    * The process will continue running after this function returns.
    * 
    * <p>If processes are not enabled, a new thread in the caller's
    * process is created and main() of <var>processClass</var> called there.
    * 
    * <p>The niceName parameter, if not an empty string, is a custom name to
    * give to the process instead of using processClass.  This allows you to
    * make easily identifyable processes even if you are using the same base
    * <var>processClass</var> to start them.
    * 
    * When invokeWith is not null, the process will be started as a fresh app
    * and not a zygote fork. Note that this is only allowed for uid 0 or when
    * debugFlags contains DEBUG_ENABLE_DEBUGGER.
    *
    * @param processClass The class to use as the process's main entry
    *                     point.
    * @param niceName A more readable name to use for the process.
    * @param uid The user-id under which the process will run.
    * @param gid The group-id under which the process will run.
    * @param gids Additional group-ids associated with the process.
    * @param debugFlags Additional flags.
    * @param targetSdkVersion The target SDK version for the app.
    * @param seInfo null-ok SELinux information for the new process.
    * @param abi non-null the ABI this app should be started with.
    * @param instructionSet null-ok the instruction set to use.
    * @param appDataDir null-ok the data directory of the app.
    * @param invokeWith null-ok the command to invoke with.
    * @param zygoteArgs Additional arguments to supply to the zygote process.
    * 
    * @return An object that describes the result of the attempt to start the process.
    * @throws RuntimeException on fatal start failure
    * 
    * {@hide}
    */
   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 invokeWith,
                                 String[] zygoteArgs) {
       return zygoteProcess.start(processClass, niceName, uid, gid, gids,
                   debugFlags, mountExternal, targetSdkVersion, seInfo,
                   abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
   }

举例:当启动一个Activity的时候,发现Activity所在进程没有被创建,就会调用这个API进程进行创建。Process.start()方法是阻塞操作,等待直到进程创建完成并返回相应的新进程pid,才完成该方法。

  ProcessStartResult  startResult = Process.start(entryPoint,
                       app.processName, uid, uid, gids, debugFlags, mountExternal,
                       app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
                       app.info.dataDir, invokeWith, entryPointArgs);
           }

为了更好的理解各个参数的含义,我debug一下,得到的各个参数值如下图(我调试的过程中发现,头条一启动就有很多进程跟着起来,做ROM工程师真是累啊,虽然只是打开一个应用,背后唤醒的都不止10个进程,每个进程都需要申请系统的资源,相信每一家ROM对进程的存活都有严格的把控!)


头条启动.png
3.2、整理进程创建的请求参数

在Process.start之后,有几个链条式的调用,Process.start->ZygoteProcess.start->ZygoteProcess.startViaZygote,返回ZygoteState,ZygoteState封装了Socket的输入和输出流,zygoteInputStream与zygoteWrite,zygoteWrite可以把创建进程的参数从SystemServer进程传递到Zygote进程,zygoteInputStream可以把返回结果从Zygote进程返回到SystemServer进程。以下几个调用就是不断的封装并传递创建进程的请求参数。

/frameworks/base/core/java/android/os/ZygoteProcess.java
195    public final Process.ProcessStartResult start(final String processClass,
196                                                  final String niceName,
197                                                  int uid, int gid, int[] gids,
198                                                  int debugFlags, int mountExternal,
199                                                  int targetSdkVersion,
200                                                  String seInfo,
201                                                  String abi,
202                                                  String instructionSet,
203                                                  String appDataDir,
204                                                  String invokeWith,
205                                                  String[] zygoteArgs) {
206        try {
207            return startViaZygote(processClass, niceName, uid, gid, gids,
208                    debugFlags, mountExternal, targetSdkVersion, seInfo,
209                    abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
210        } catch (ZygoteStartFailedEx ex) {
211            Log.e(LOG_TAG,
212                    "Starting VM process through Zygote failed");
213            throw new RuntimeException(
214                    "Starting VM process through Zygote failed", ex);
215        }
216    }
 /frameworks/base/core/java/android/os/ZygoteProcess.java
329    private Process.ProcessStartResult startViaZygote(final String processClass,
330                                                      final String niceName,
331                                                      final int uid, final int gid,
332                                                      final int[] gids,
333                                                      int debugFlags, int mountExternal,
334                                                      int targetSdkVersion,
335                                                      String seInfo,
336                                                      String abi,
337                                                      String instructionSet,
338                                                      String appDataDir,
339                                                      String invokeWith,
340                                                      String[] extraArgs)
341                                                      throws ZygoteStartFailedEx {
342        ArrayList<String> argsForZygote = new ArrayList<String>();
            ......
430        synchronized(mLock) {
431            return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
432        }
433    }

该过程主要工作是生成argsForZygote列表,把startViaZygote方法的参数存放到这个列表里面。并且调用zygoteSendArgsAndGetResult请求Zygotefork进程。

3.3、创建Socket,给Zygote进程发送进程创建的请求参数
 /frameworks/base/core/java/android/os/ZygoteProcess.java
454    @GuardedBy("mLock")
455    private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
456        Preconditions.checkState(Thread.holdsLock(mLock), "ZygoteProcess lock not held");
457
458        if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
459            try {
460                primaryZygoteState = ZygoteState.connect(mSocket);
461            } catch (IOException ioe) {
462                throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
463            }
464        }
465
466        if (primaryZygoteState.matches(abi)) {
467            return primaryZygoteState;
468        }
469
470        // The primary zygote didn't match. Try the secondary.
471        if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
472            try {
473                secondaryZygoteState = ZygoteState.connect(mSecondarySocket);
474            } catch (IOException ioe) {
475                throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
476            }
477        }
478        //判断当前的abi来选择与zygote还是zygote64来进行通信
479        if (secondaryZygoteState.matches(abi)) {
480            return secondaryZygoteState;
481        }
482
483        throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
484    }

通过前面的文章可知道,Zygote进程有两个Socket,这里当主zygote没能匹配成功,则尝试第二个mSecondarySocket来连接。

 /frameworks/base/core/java/android/os/ZygoteProcess.java
92        public static ZygoteState connect(String socketAddress) throws IOException {
93            DataInputStream zygoteInputStream = null;
94            BufferedWriter zygoteWriter = null;
95            final LocalSocket zygoteSocket = new LocalSocket();
96
97            try {
98                zygoteSocket.connect(new LocalSocketAddress(socketAddress,
99                        LocalSocketAddress.Namespace.RESERVED));
100
101                zygoteInputStream = new DataInputStream(zygoteSocket.getInputStream());
102
103                zygoteWriter = new BufferedWriter(new OutputStreamWriter(
104                        zygoteSocket.getOutputStream()), 256);
105            } catch (IOException ex) {
106                try {
107                    zygoteSocket.close();
108                } catch (IOException ignore) {
109                }
110
111                throw ex;
112            }
113
114            String abiListString = getAbiList(zygoteWriter, zygoteInputStream);
115            Log.i("Zygote", "Process: zygote socket " + socketAddress + " opened, supported ABIS: "
116                    + abiListString);
117
118            return new ZygoteState(zygoteSocket, zygoteInputStream, zygoteWriter,
119                    Arrays.asList(abiListString.split(",")));
120        }

这个方法主要是建立了SystemServer(Client)这一边的Socket---LocalSocket,与Zygote进程的LocalServerSocket成功连接之后,获取这个LocalSocket的输入流zygoteInputStream与输出流zygoteWriter,并且将他们封装到ZygoteState中再返回。关于Socket的工作原理,移步本系列第三篇博客。

253    @GuardedBy("mLock")
254    private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
255            ZygoteState zygoteState, ArrayList<String> args)
256            throws ZygoteStartFailedEx {
257        try {
258            // Throw early if any of the arguments are malformed. This means we can
259            // avoid writing a partial response to the zygote.
260            int sz = args.size();
261            for (int i = 0; i < sz; i++) {
262                if (args.get(i).indexOf('\n') >= 0) {
263                    throw new ZygoteStartFailedEx("embedded newlines not allowed");
264                }
265            }
266
               ........
                  //1、从ZygoteState中取出输入流和输出流
277            final BufferedWriter writer = zygoteState.writer;
278            final DataInputStream inputStream = zygoteState.inputStream;
279            //2、用输入流将创建进程的参数传递给Zygote进程
280            writer.write(Integer.toString(args.size()));
281            writer.newLine();
282
283            for (int i = 0; i < sz; i++) {
284                String arg = args.get(i);
285                writer.write(arg);
286                writer.newLine();
287            }
288
289            writer.flush();
290
291            //创建Process.ProcessStartResult用于存放fork进程的返回结果
292            Process.ProcessStartResult result = new Process.ProcessStartResult();
293
294            // Always read the entire result from the input stream to avoid leaving
295            // bytes in the stream for future process starts to accidentally stumble
296            // upon.
                  //输入流读取Zygote进程创建进程之后返回的数据,保存在Process.ProcessStartResult中
297            result.pid = inputStream.readInt();
298            result.usingWrapper = inputStream.readBoolean();
299            //通过判断result.pid 是否创建成功
300            if (result.pid < 0) {
301                throw new ZygoteStartFailedEx("fork() failed");
302            }
303            return result;
304        } catch (IOException ex) {
305            zygoteState.close();
306            throw new ZygoteStartFailedEx(ex);
307        }
308    }

这段做的工作主要是从ZygoteState中取出输入流和输出流,然后和Server端的Zygote进程的LocketServerSocket进行通信。将AMS中创建进程的参数传递给Zygote进程。Zygote进程fork完成之后, inputStream.readInt()就能读取出返回结果,如果小于0,代表创建失败,不小于0代表创建成功。
这段代码存在一个问题,如果Zygote进程fork进程超时,System这段迟迟不能get到返回结果,会引起什么后果?

试想一下,当 AMS 需要创建进程时, 会通过 Socket 与 zygote 进程通信, 当 zygote 接收到请求后会 fork 出一个子进程, 并将其 pid 返回给 AMS。需要注意的是, 在收到 pid 之前, AMS 会一直持锁等待,而且这里持有的是AMS大锁, 所以就会 block 其他重要线程, 导致系统卡死,用户反馈内容也会主要围绕 "系统卡死" "按键没有反应" 等等。

那如何解决这个问题?google其实有注意到,准备加一个超时机制,但是一直没有加上,但是这种情况也是治标不治本,解决这种问题还是要具体分析,是内存碎片严重导致fork进程申请page失败,还是其他原因,需要根据Log具体对待。

3.4、Zygote进程接收请求参数

到这里,Client段的工作就全部看完了,现在去看看Socket的服务端。再次回顾一下那段“模板”代码。

  frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
 public static void main(String argv[]) {
        //1、创建ZygoteServer
        ZygoteServer zygoteServer = new ZygoteServer();
        try {
            //2、创建一个Server端的Socket
            zygoteServer.registerServerSocket(socketName);
            //3、加载进程的资源和类
            preload(bootTimingsTraceLog);
            if (startSystemServer) {
                //4、开启SystemServer进程,这是受精卵进程的第一次分裂
                startSystemServer(abiList, socketName, zygoteServer);
            }
            //5、启动一个死循环监听来自Client端的消息
            zygoteServer.runSelectLoop(abiList);
             //6、关闭SystemServer的Socket
            zygoteServer.closeServerSocket();
        } catch (Zygote.MethodAndArgsCaller caller) {
             //7、这里捕获这个异常调用MethodAndArgsCaller的run方法。
            caller.run();
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            zygoteServer.closeServerSocket();
            throw ex;
        }
    }

注释写的很详细了,不多做解释,直接看runSelectLoop方法。

 /frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
136    void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {
137        ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
138        ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
139        //将服务端LocalServerSocket的fd加进fds中
140        fds.add(mServerSocket.getFileDescriptor());
141        peers.add(null);
142
143        while (true) {
144            StructPollfd[] pollFds = new StructPollfd[fds.size()];
145            for (int i = 0; i < pollFds.length; ++i) {
146                pollFds[i] = new StructPollfd();
147                pollFds[i].fd = fds.get(i);
148                pollFds[i].events = (short) POLLIN;
149            }
150            try {
                    //处理轮询状态,当pollFds有事件到来则往下执行,否则阻塞在这里
151                Os.poll(pollFds, -1);
152            } catch (ErrnoException ex) {
153                throw new RuntimeException("poll failed", ex);
154            }
                //当接收到客户端发出连接请求 或者数据处理请求到来,则往下执行;否则进入continue,跳出本次循环。
155            for (int i = pollFds.length - 1; i >= 0; --i) {
156                if ((pollFds[i].revents & POLLIN) == 0) {
157                    continue;
158                }
                     //当i为0的时候,创建ZygoteConnection,实质就创建LocalServerSocket
159                if (i == 0) {
160                    ZygoteConnection newPeer = acceptCommandPeer(abiList);
161                    peers.add(newPeer);
                          //将LocalServerSocket的fd添加到fds
162                    fds.add(newPeer.getFileDesciptor());
163                } else {
                          将LocalServerSocket的fd取出来,执行runOnce
164                    boolean done = peers.get(i).runOnce(this);
165                    if (done) {
                              //完成之后将fd与ZygoteConnection移除
166                        peers.remove(i);
167                        fds.remove(i);
168                    }
169                }
170            }
171        }
172    }
173}

runSelectLoop中有一个while死循环,接收进程创建请求,当来了一个请求,就会走runOnce方法

78    /**
79     * Waits for and accepts a single command connection. Throws
80     * RuntimeException on failure.
81     */
82    private ZygoteConnection acceptCommandPeer(String abiList) {
83        try {
84            return createNewConnection(mServerSocket.accept(), abiList);
85        } catch (IOException ex) {
86            throw new RuntimeException(
87                    "IOException during accept()", ex);
88        }
89    }

acceptCommandPeer中调用createNewConnection,返回值是一个ZygoteConnection,封装了mServerSocket的输入流mSocketReader与输出流mSocketOutStream,这个与Clinet端的ZygoteState有着异曲同工之妙啊。

/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
91    ZygoteConnection(LocalSocket socket, String abiList) throws IOException {
92        mSocket = socket;
93        this.abiList = abiList;
94        
95        mSocketOutStream
96                = new DataOutputStream(socket.getOutputStream());
97
98        mSocketReader = new BufferedReader(
99                new InputStreamReader(socket.getInputStream()), 256);
100
101        mSocket.setSoTimeout(CONNECTION_TIMEOUT_MILLIS);
102
103        try {
104            peer = mSocket.getPeerCredentials();
105        } catch (IOException ex) {
106            Log.e(TAG, "Cannot read peer credentials", ex);
107            throw ex;
108        }
109    }
3.5、Zygote进程处理创建进程请求,fork进程

在ZygoteConnection创建好了之后,就执行runOnce真正处理进程的创建请求了。

/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
134    boolean runOnce(ZygoteServer zygoteServer) throws Zygote.MethodAndArgsCaller {
135
136        String args[];
137        Arguments parsedArgs = null;
138        FileDescriptor[] descriptors;
139
140        try {
                 //把进程创建的参数读取出来
141            args = readArgumentList();
142            descriptors = mSocket.getAncillaryFileDescriptors();
143        } catch (IOException ex) {
144            Log.w(TAG, "IOException on command socket " + ex.getMessage());
145            closeSocket();
146            return true;
147        }
148
149        if (args == null) {
150            // EOF reached.
                  //参数为null,需要关闭之前创建的Socket,进程创建请求参数为null还没有仔细的调查过
151            closeSocket();
152            return true;
153        }
              ........
162
163        int pid = -1;
164        FileDescriptor childPipeFd = null;
165        FileDescriptor serverPipeFd = null;
166
167        try {
                  //将进程创建请求参数整理成Arguments对象 
168            parsedArgs = new Arguments(args);
               ........
238            //创建子进程,底层调用fork函数,返回值有两个,基于写时复制
239            pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
240                    parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
241                    parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
242                    parsedArgs.appDataDir);
243        } catch (ErrnoException ex) {
244            logAndPrintError(newStderr, "Exception creating pipe", ex);
245        } catch (IllegalArgumentException ex) {
246            logAndPrintError(newStderr, "Invalid zygote arguments", ex);
247        } catch (ZygoteSecurityException ex) {
248            logAndPrintError(newStderr,
249                    "Zygote security policy prevents request: ", ex);
250        }
251
252        try {
                 //pid==0代表是新创建的子进程
253            if (pid == 0) {
254                //关闭从Zygote进程继承而来的Socket
255                zygoteServer.closeServerSocket();
256                IoUtils.closeQuietly(serverPipeFd);
257                serverPipeFd = null;
                      //处理子进程接下来的工作
258                handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
259
260                // should never get here, the child is expected to either
261                // throw Zygote.MethodAndArgsCaller or exec().
262                return true;
263            } else {
264               //大于0,是父进程,也就是Zygote进程
265                IoUtils.closeQuietly(childPipeFd);
266                childPipeFd = null;
                     //处理父进程接下来的工作
267                return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
268            }
269        } finally {
270            IoUtils.closeQuietly(childPipeFd);
271            IoUtils.closeQuietly(serverPipeFd);
272        }
273    }

在调用Zygote.forkAndSpecialize之前,需要调用readArgumentList把创建进程的请求参数从Socket中读取出来,放在一个名为result的String数组中。

/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
631    /**
632     * Reads an argument list from the command socket/
633     * @return Argument list or null if EOF is reached
634     * @throws IOException passed straight through
635     */
636    private String[] readArgumentList()
637            throws IOException {
            ......
649        int argc;
650
651        try {
652            String s = mSocketReader.readLine();
653
654            if (s == null) {
655                // EOF reached.
656                return null;
657            }
658            argc = Integer.parseInt(s);
659        } catch (NumberFormatException ex) {
660            Log.e(TAG, "invalid Zygote wire format: non-int at argc");
661            throw new IOException("invalid wire format");
662        }
663
664        // See bug 1092107: large argc can be used for a DOS attack
665        if (argc > MAX_ZYGOTE_ARGC) {
666            throw new IOException("max arg count exceeded");
667        }
668
669        String[] result = new String[argc];
670        for (int i = 0; i < argc; i++) {
671            result[i] = mSocketReader.readLine();
672            if (result[i] == null) {
673                // We got an unexpected EOF.
674                throw new IOException("truncated request");
675            }
676        }
677
678        return result;
679    }

参数有了就调用Zygote.forkAndSpecialize方法fork进程了,关于进程的fork,第三篇写的更详细,这里不赘述。

99    public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
100          int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
101          int[] fdsToIgnore, String instructionSet, String appDataDir) {
102        VM_HOOKS.preFork();
103        // Resets nice priority for zygote process.
104        resetNicePriority();
             //jni技术调用fork函数
105        int pid = nativeForkAndSpecialize(
106                  uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
107                  fdsToIgnore, instructionSet, appDataDir);
108        // Enable tracing as soon as possible for the child process.
109        if (pid == 0) {
110            Trace.setTracingEnabled(true);
111
112            // Note that this event ends at the end of handleChildProc,
113            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
114        }
115        VM_HOOKS.postForkCommon();
116        return pid;
117    }
3.6、进程创建成功,新进程做初始化

当forkAndSpecialize完成之后,进程就被创建出来了,但是这个进程是光秃秃的,还需一些工作要处理,即走进handleChildProc方法。

786    private void handleChildProc(Arguments parsedArgs,
787            FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
788            throws Zygote.MethodAndArgsCaller {
               .......
               //设置进程名字
811        if (parsedArgs.niceName != null) {
812            Process.setArgV0(parsedArgs.niceName);
813        }
814
815        // End of the postFork event.
816        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
817        if (parsedArgs.invokeWith != null) {
818            WrapperInit.execApplication(parsedArgs.invokeWith,
819                    parsedArgs.niceName, parsedArgs.targetSdkVersion,
820                    VMRuntime.getCurrentInstructionSet(),
821                    pipeFd, parsedArgs.remainingArgs);
822        } else {
                   //做进程的一些初始化操作,与System进程创建一致的
823            ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion,
824                    parsedArgs.remainingArgs, null /* classLoader */);
825        }
826    }
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
829    public static final void zygoteInit(int targetSdkVersion, String[] argv,
830            ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {
831        if (RuntimeInit.DEBUG) {
832            Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
833        }
834
835        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
          //见本系列第三篇文章3.5.1
836        RuntimeInit.redirectLogStreams();
837       //见本系列第三篇文章3.5.2
838        RuntimeInit.commonInit();
           //见本系列第三篇文章3.5.3
839        ZygoteInit.nativeZygoteInit();
          //见本系列第三篇文章3.5.4
840        RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
841    }
842

zygoteInit与System进程创建是一致的,每个进程在创建出来之后,都需要做四件事情。

  • 重定向log输出
  • 通用的一些初始化,比如设置进程的异常捕获方式、时区等
  • 调用nativeZygoteInit进行Zygote的初始化,开启Binder线程池
  • 调用applicationInit进行应用的初始化
    在此不赘述,可移步见本系列第三篇文章。这里看一下applicationInit进行应用的初始化。
 /frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
289    protected static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
290            throws Zygote.MethodAndArgsCaller {
              .....
303        final Arguments args;
304        try {
305            args = new Arguments(argv);
306        } catch (IllegalArgumentException ex) {
307            Slog.e(TAG, ex.getMessage());
308            // let the process exit
309            return;
310        }
              .....
315        // 唤醒进程的main方法
316        invokeStaticMain(args.startClass, args.startArgs, classLoader);
317    }

此处的args.startClass为android.app.ActivityThread.java,当fork System进程的时候,args.startClass为com.android.server.SystemServer.java。

/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
231    private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
232            throws Zygote.MethodAndArgsCaller {
233        Class<?> cl;
234
235        try {
236            cl = Class.forName(className, true, classLoader);
237        } catch (ClassNotFoundException ex) {
238            throw new RuntimeException(
239                    "Missing class when invoking static main " + className,
240                    ex);
241        }
242
243        Method m;
244        try {
                  //"main是写死的,Android所有应用进程的入口就是android.app.ActivityThread.java中的main方法
245            m = cl.getMethod("main", new Class[] { String[].class });
246        } catch (NoSuchMethodException ex) {
247            throw new RuntimeException(
248                    "Missing static main on " + className, ex);
249        } catch (SecurityException ex) {
250            throw new RuntimeException(
251                    "Problem getting static main on " + className, ex);
252        }
        .......
266        throw new Zygote.MethodAndArgsCaller(m, argv);
267    }

invokeStaticMain主要反射了android.app.ActivityThread.java中的main方法,得到Method对象m,为了清除栈帧,为新创建的进行一个干净的环境,最后抛出一个异常Zygote.MethodAndArgsCaller。这个异常会在ZygoteInit的main中被捕获。

  frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
 public static void main(String argv[]) {
       .....
            //1、启动一个死循环监听来自Client端的消息
            zygoteServer.runSelectLoop(abiList);
             //2、关闭SystemServer的Socket
            zygoteServer.closeServerSocket();
        } catch (Zygote.MethodAndArgsCaller caller) {
             //3、这里捕获这个异常调用MethodAndArgsCaller的run方法。
            caller.run();
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            zygoteServer.closeServerSocket();
            throw ex;
        }
    }

捕获之后,调用MethodAndArgsCaller的run方法,终于进入了ActivityThread的main方法了,一个有血有肉的进程就启动成功了。

225    public static class MethodAndArgsCaller extends Exception
226            implements Runnable {
227        /** method to call */
228        private final Method mMethod;
229
230        /** argument array */
231        private final String[] mArgs;
232
233        public MethodAndArgsCaller(Method method, String[] args) {
234            mMethod = method;
235            mArgs = args;
236        }
237
238        public void run() {
239            try {
240                mMethod.invoke(null, new Object[] { mArgs });
241            } catch (IllegalAccessException ex) {
242                throw new RuntimeException(ex);
243            } catch (InvocationTargetException ex) {
244                Throwable cause = ex.getCause();
245                if (cause instanceof RuntimeException) {
246                    throw (RuntimeException) cause;
247                } else if (cause instanceof Error) {
248                    throw (Error) cause;
249                }
250                throw new RuntimeException(ex);
251            }
252        }
253    }
254}

进程被创建出来了,系统中资源和类我们就可以直接使用了,这是怎么回事?由于Android系统基本所有进程的创建都是交给Zygote进程创建的,而进程的fork基于写时复制技术,所以Zygote进程启动时候加载的资源也会被应用进程所使用,如下图,原来进程中所需要的资源,库等都是由它老子办好了,继承过来就行。资源的加载过程参考本系列第二篇博客。

Zygote进程fork进程.png

四、总结

应用进程的创建和System进程的创建基本上一致,尤其是在fork进程之后的逻辑,是一模一样的,不同的是,System进程是Zygote进程的大儿子,由自己亲手创建,而其他应用进程是通过Process.start发送创建请求,Zygote帮忙创建的。这个过程其实不算复杂,创建流程的详细序列图如下。

进程的创建序列图,右键查看大图更清晰.png

进程的创建花了四篇的篇幅,从Zygote进程的创建,System进程的创建和启动,在到应用进程的创建,到此就结束了,下面将会梳理AMS中进程的数据结构---ProcessRecord。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342