上一篇文章《Android应用程序的启动逻辑-中间层》,从源码的角度分析了客户端的逻辑。主要是socket连接,应用启动参数发送,以及状态读取。
本文承接上文,从源码的角度分析服务端的socket创建、监听和执行应用启动等逻辑。主要涉及文件:
Frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
Frameworks/base/core/java/com/android/internal/os/ZygoteServer.java
Frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
Frameworks/base/core/java/android/net/LocalServerSocket.java
Frameworks/base/core/java/android/net/LocalSocketImpl.java
在前面的文章中,已经分析过zygote进程的启动逻辑,zygote进程启动过程中会执行到ZygoteInit的main()方法。本文以此为切入点,zygote进程的main()方法,会创建socket server,然后进入loop等待客户端进程发起连接。主要是下面三行代码,表示主流程:
Frameworks/base/core/java/com/android/internal/os/ZygoteInit.java : main()
下面会逐一进行展开,阅读分析每个步骤里面的逻辑,依次是:ZygoteServer初始化、注册socket server、loop逻辑、客户端连接响应逻辑。
ZygoteServer初始化
ZygoteServer是被Zygote进程使用的socket server类。这个类提供等待UNIX domain socket命令并创建子进程的功能。
构造方法是空的,ZygoteServer初始化不做任何动作:
注册socket server
这里涉及到一个知识点,环境变量ANDROID_SOCKET_zygote是init进程在解析init.zygote32.rc文件时,根据socket行,设置的。
loop逻辑
zygote进程从这里开始进入无限循环逻辑。这里涉及到一个知识点,Linux内核中的一种IO事件处理机制epoll。在整个Android系统中,这个机制被大量使用。简单来说,通过epoll机制,监控文件描述符,当文件发生读写事件时,会立刻通知相应的应用程序去执行读写操作。epoll是同步IO,会阻塞当前进程。
客户端连接处理逻辑
继续上一节ZygoteConnection.processOneCommand()。这里涉及到fork()的知识点,fork()返回的pid值在父进程和子进程是不一样的。父进程返回的pid是子进程的pid值(大于0),子进程返回的pid值是0。
至此,如果是主进程zygote,会返回null,继续loop循环,分析到此为止。如果是子进程,执行完handleChildProc()方法,会跳出loop循环,继续子进程后面的逻辑。下面继续子进程的处理逻辑。
子进程处理程序
继续上一节的ZygoteConnection.handleChildProc()
ZygoteInit.zygoteInit()
写在结尾的话
至此,zygote进程如何注册zygote socket server,如何监听处理system_server进程的应用程序启动请求,以及应用程序进程的前置逻辑,就分析完了。
接下来,会继续分析应用程序进程的启动逻辑(实际逻辑)。