Android 10.0系统启动之Zygote进程(三)-「Android取经之路」
前几节已经讲完了Android10.0的Init启动过程以及Zygote架构。
Android系统启动之init进程(一)-「Android取经之路」
Android系统启动之init进程(二)-「Android取经之路」
Android 10.0系统启动之init进程(三)-「Android取经之路」
Android 10.0系统启动之init进程(四)-「Android取经之路」
Android 10.0系统启动之Zygote进程(一)-「Android取经之路」
Android 10.0系统启动之Zygote进程(二)-「Android取经之路」
Android 10.0系统启动之Zygote进程(二)-「Android取经之路」
本节主要分析Zygote进程在JAVA世界的启动源码
4.2 Java世界的Zygote启动主要代码调用流程:
上节我们通过JNI调用ZygoteInit的main函数后,Zygote便进入了Java框架层,此前没有任何代码进入过Java框架层,换句换说Zygote开创了Java框架层。
4.2.1 [ZygoteInit.java]main.cpp
path:frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
main的主要工作:
1.调用preload()来预加载类和资源
2.调用ZygoteServer()创建两个Server端的Socket--/dev/socket/zygote 和 /dev/socket/zygote_secondary,Socket用来等待ActivityManagerService来请求Zygote来创建新的应用程序进程。
3.调用forkSystemServer 来启动SystemServer进程,这样系统的关键服务也会由SystemServer进程启动起来。
4.最后调用runSelectLoop函数来等待客户端请求
后面我们主要来分析这四件事。
public static void main(String argv[]) {
// 1.创建ZygoteServer
ZygoteServer zygoteServer = null;
// 调用native函数,确保当前没有其它线程在运行
ZygoteHooks.startZygoteNoThreadCreation();
//设置pid为0,Zygote进入自己的进程组
Os.setpgid(0, 0);
......
Runnable caller;
try {
......
//得到systrace的监控TAG
String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";
TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,
Trace.TRACE_TAG_DALVIK);
//通过systradce来追踪 函数ZygoteInit, 可以通过systrace工具来进行分析
//traceBegin 和 traceEnd 要成对出现,而且需要使用同一个tag
bootTimingsTraceLog.traceBegin("ZygoteInit");
//开启DDMS(Dalvik Debug Monitor Service)功能
//注册所有已知的Java VM的处理块的监听器。线程监听、内存监听、native 堆内存监听、debug模式监听等等
RuntimeInit.enableDdms();
boolean startSystemServer = false;
String zygoteSocketName = "zygote";
String abiList = null;
boolean enableLazyPreload = false;
//2. 解析app_main.cpp - start()传入的参数
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = true; //启动zygote时,才会传入参数:start-system-server
} else if ("--enable-lazy-preload".equals(argv[i])) {
enableLazyPreload = true; //启动zygote_secondary时,才会传入参数:enable-lazy-preload
} else if (argv[i].startsWith(ABI_LIST_ARG)) { //通过属性ro.product.cpu.abilist64\ro.product.cpu.abilist32 从C空间传来的值
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length()); //会有两种值:zygote和zygote_secondary
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
// 根据传入socket name来决定是创建socket还是zygote_secondary
final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);
// 在第一次zygote启动时,enableLazyPreload为false,执行preload
if (!enableLazyPreload) {
//systrace 追踪 ZygotePreload
bootTimingsTraceLog.traceBegin("ZygotePreload");
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
// 3.加载进程的资源和类,参考[4.2.2]
preload(bootTimingsTraceLog);
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
//systrae结束 ZygotePreload的追踪
bootTimingsTraceLog.traceEnd(); // ZygotePreload
} else {
// 延迟预加载, 变更Zygote进程优先级为NORMAL级别,第一次fork时才会preload
Zygote.resetNicePriority();
}
//结束ZygoteInit的systrace追踪
bootTimingsTraceLog.traceEnd(); // ZygoteInit
//禁用systrace追踪,以便fork的进程不会从zygote继承过时的跟踪标记
Trace.setTracingEnabled(false, 0);
// 4.调用ZygoteServer 构造函数,创建socket,会根据传入的参数,
// 创建两个socket:/dev/socket/zygote 和 /dev/socket/zygote_secondary
//参考[4.2.3]
zygoteServer = new ZygoteServer(isPrimaryZygote);
if (startSystemServer) {
//5. fork出system server,参考[4.2.4]
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
// 启动SystemServer
if (r != null) {
r.run();
return;
}
}
// 6. zygote进程进入无限循环,处理请求
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
if (zygoteServer != null) {
zygoteServer.closeServerSocket();
}
}
// 7.在子进程中退出了选择循环。继续执行命令
if (caller != null) {
caller.run();
}
}
日志:
01-10 11:20:32.219 722 722 D Zygote : begin preload
01-10 11:20:32.219 722 722 I Zygote : Calling ZygoteHooks.beginPreload()
01-10 11:20:32.249 722 722 I Zygote : Preloading classes...
01-10 11:20:33.179 722 722 I Zygote : ...preloaded 7587 classes in 926ms.
01-10 11:20:33.449 722 722 I Zygote : Preloading resources...
01-10 11:20:33.459 722 722 I Zygote : ...preloaded 64 resources in 17ms.
01-10 11:20:33.519 722 722 I Zygote : Preloading shared libraries...
01-10 11:20:33.539 722 722 I Zygote : Called ZygoteHooks.endPreload()
01-10 11:20:33.539 722 722 I Zygote : Installed AndroidKeyStoreProvider in 1ms.
01-10 11:20:33.549 722 722 I Zygote : Warmed up JCA providers in 11ms.
01-10 11:20:33.549 722 722 D Zygote : end preload
01-10 11:20:33.649 722 722 D Zygote : Forked child process 1607
01-10 11:20:33.649 722 722 I Zygote : System server process 1607 has been created
01-10 11:20:33.649 722 722 I Zygote : Accepting command socket connections
10-15 06:11:07.749 722 722 D Zygote : Forked child process 2982
10-15 06:11:07.789 722 722 D Zygote : Forked child process 3004
4.2.2 [ZygoteInit.java] preload()
static void preload(TimingsTraceLog bootTimingsTraceLog) {
Log.d(TAG, "begin preload");
·
}
什么是预加载:
预加载是指在zygote进程启动的时候就加载,这样系统只在zygote执行一次加载操作,所有APP用到该资源不需要再重新加载,减少资源加载时间,加快了应用启动速度,一般情况下,系统中App共享的资源会被列为预加载资源。
zygote fork子进程时,根据fork的copy-on-write机制可知,有些类如果不做改变,甚至都不用复制,子进程可以和父进程共享这部分数据,从而省去不少内存的占用。
预加载的原理:
zygote进程启动后将资源读取出来,保存到Resources一个全局静态变量中,下次读取系统资源的时候优先从静态变量中查找。
frameworks/base/config/preloaded-classes:
参考:
相关日志:
01-10 11:20:32.219 722 722 D Zygote : begin preload
01-10 11:20:32.219 722 722 I Zygote : Calling ZygoteHooks.beginPreload()
01-10 11:20:32.249 722 722 I Zygote : Preloading classes...
01-10 11:20:33.179 722 722 I Zygote : ...preloaded 7587 classes in 926ms.
01-10 11:20:33.539 722 722 I Zygote : Called ZygoteHooks.endPreload()
01-10 11:20:33.549 722 722 D Zygote : end preload
4.2.3 [ZygoteServer.java] ZygoteServer()
path: frameworks\base\core\java\com\android\internal\os\ZygoteServer.java
作用:ZygoteServer 构造函数初始化时,根据传入的参数,利用LocalServerSocket 创建了4个本地服务端的socket,用来建立连接,
分别是:zygote、usap_pool_primary、zygote_secondary、usap_pool_secondary
private LocalServerSocket mZygoteSocket;
private LocalServerSocket mUsapPoolSocket;
//创建zygote的socket
ZygoteServer(boolean isPrimaryZygote) {
mUsapPoolEventFD = Zygote.getUsapPoolEventFD();
if (isPrimaryZygote) {
//创建socket,并获取socket对象,socketname:zygote
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
//创建socket,并获取socket对象,socketname:usap_pool_primary
mUsapPoolSocket =
Zygote.createManagedSocketFromInitSocket(
Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);
} else {
//创建socket,并获取socket对象,socketname:zygote_secondary
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME);
//创建socket,并获取socket对象,socketname:usap_pool_secondary
mUsapPoolSocket =
Zygote.createManagedSocketFromInitSocket(
Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);
}
fetchUsapPoolPolicyProps();
mUsapPoolSupported = true;
}
static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
int fileDesc;
// ANDROID_SOCKET_PREFIX为"ANDROID_SOCKET_"
//加入传入参数为zygote,则fullSocketName:ANDROID_SOCKET_zygote
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
//init.zygote64_32.rc启动时,指定了4个socket:
//分别是zygote、usap_pool_primary、zygote_secondary、usap_pool_secondary
// 在进程被创建时,就会创建对应的文件描述符,并加入到环境变量中
// 这里取出对应的环境变量
String env = System.getenv(fullSocketName);
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException("Socket unset or invalid: " + fullSocketName, ex);
}
try {
FileDescriptor fd = new FileDescriptor();
fd.etInt$(fileDesc); // 获取zygote socket的文件描述符
return new LocalServerSocket(fd); // 创建Socket的本地服务端
} catch (IOException ex) {
throw new RuntimeException(
"Error building socket from file descriptor: " + fileDesc, ex);
}
}
path: \frameworks\base\core\java\android\net\LocalServerSocket.java
public LocalServerSocket(FileDescriptor fd) throws IOException
{
impl = new LocalSocketImpl(fd);
impl.listen(LISTEN_BACKLOG);
localAddress = impl.getSockAddress();
}
4.2.4 [ZygoteInit.java] forkSystemServer()
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
long capabilities = posixCapabilitiesAsBits(
OsConstants.CAP_IPC_LOCK,
OsConstants.CAP_KILL,
OsConstants.CAP_NET_ADMIN,
OsConstants.CAP_NET_BIND_SERVICE,
OsConstants.CAP_NET_BROADCAST,
OsConstants.CAP_NET_RAW,
OsConstants.CAP_SYS_MODULE,
OsConstants.CAP_SYS_NICE,
OsConstants.CAP_SYS_PTRACE,
OsConstants.CAP_SYS_TIME,
OsConstants.CAP_SYS_TTY_CONFIG,
OsConstants.CAP_WAKE_ALARM,
OsConstants.CAP_BLOCK_SUSPEND
);
......
//参数准备
/* Hardcoded command line to start the system server */
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
+ "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
"com.android.server.SystemServer",
};
ZygoteArguments parsedArgs = null;
int pid;
try {
//将上面准备的参数,按照ZygoteArguments的风格进行封装
parsedArgs = new ZygoteArguments(args);
Zygote.applyDebuggerSystemProperty(parsedArgs);
Zygote.applyInvokeWithSystemProperty(parsedArgs);
boolean profileSystemServer = SystemProperties.getBoolean(
"dalvik.vm.profilesystemserver", false);
if (profileSystemServer) {
parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
}
//通过fork"分裂"出子进程system_server
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.mUid, parsedArgs.mGid,
parsedArgs.mGids,
parsedArgs.mRuntimeFlags,
null,
parsedArgs.mPermittedCapabilities,
parsedArgs.mEffectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
//进入子进程system_server
/* For child process */
if (pid == 0) {
// 处理32_64和64_32的情况
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
// fork时会copy socket,system server需要主动关闭
zygoteServer.closeServerSocket();
// system server进程处理自己的工作
return handleSystemServerProcess(parsedArgs);
}
return null;
}
ZygoteInit。forkSystemServer()会在新fork出的子进程中调用 handleSystemServerProcess(),
主要是返回Runtime.java的MethodAndArgsCaller的方法,然后通过r.run() 启动com.android.server.SystemServer的main 方法
这个当我们后面的SystemServer的章节进行详细讲解。
handleSystemServerProcess代码流程:
handleSystemServerProcess()
|
[ZygoteInit.java]
zygoteInit()
|
[RuntimeInit.java]
applicationInit()
|
findStaticMain()
|
MethodAndArgsCaller()
4.2.5 [ZygoteServer.java] runSelectLoop()
path: 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>();
// 首先将server socket加入到fds
socketFDs.add(mZygoteSocket.getFileDescriptor());
peers.add(null);
while (true) {
fetchUsapPoolPolicyPropsWithMinInterval();
int[] usapPipeFDs = null;
StructPollfd[] pollFDs = null;
// 每次循环,都重新创建需要监听的pollFds
// Allocate enough space for the poll structs, taking into account
// the state of the USAP pool for this Zygote (could be a
// regular Zygote, a WebView Zygote, or an AppZygote).
if (mUsapPoolEnabled) {
usapPipeFDs = Zygote.getUsapPipeFDs();
pollFDs = new StructPollfd[socketFDs.size() + 1 + usapPipeFDs.length];
} else {
pollFDs = new StructPollfd[socketFDs.size()];
}
/*
* For reasons of correctness the USAP pool pipe and event FDs
* must be processed before the session and server sockets. This
* is to ensure that the USAP pool accounting information is
* accurate when handling other requests like API blacklist
* exemptions.
*/
int pollIndex = 0;
for (FileDescriptor socketFD : socketFDs) {
// 关注事件到来
pollFDs[pollIndex] = new StructPollfd();
pollFDs[pollIndex].fd = socketFD;
pollFDs[pollIndex].events = (short) POLLIN;
++pollIndex;
}
final int usapPoolEventFDIndex = pollIndex;
if (mUsapPoolEnabled) {
pollFDs[pollIndex] = new StructPollfd();
pollFDs[pollIndex].fd = mUsapPoolEventFD;
pollFDs[pollIndex].events = (short) POLLIN;
++pollIndex;
for (int usapPipeFD : usapPipeFDs) {
FileDescriptor managedFd = new FileDescriptor();
managedFd.setInt$(usapPipeFD);
pollFDs[pollIndex] = new StructPollfd();
pollFDs[pollIndex].fd = managedFd;
pollFDs[pollIndex].events = (short) POLLIN;
++pollIndex;
}
}
try {
// 等待事件到来
Os.poll(pollFDs, -1);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
boolean usapPoolFDRead = false;
//倒序处理,即优先处理已建立链接的信息,后处理新建链接的请求
while (--pollIndex >= 0) {
if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
continue;
}
// server socket最先加入fds, 因此这里是server socket收到数据
if (pollIndex == 0) {
// 收到新的建立通信的请求,建立通信连接
ZygoteConnection newPeer = acceptCommandPeer(abiList);
// 加入到peers和fds, 即下一次也开始监听
peers.add(newPeer);
socketFDs.add(newPeer.getFileDescriptor());
} else if (pollIndex < usapPoolEventFDIndex) {
//说明接收到AMS发送过来创建应用程序的请求,调用processOneCommand
//来创建新的应用程序进程
// Session socket accepted from the Zygote server socket
try {
//有socket连接,创建ZygoteConnection对象,并添加到fds。
ZygoteConnection connection = peers.get(pollIndex);
//处理连接,参考[4.2.6]
final Runnable command = connection.processOneCommand(this);
// TODO (chriswailes): Is this extra check necessary?
if (mIsForkChild) {
// We're in the child. We should always have a command to run at this
// stage if processOneCommand hasn't called "exec".
if (command == null) {
throw new IllegalStateException("command == null");
}
return command;
} else {
// We're in the server - we should never have any commands to run.
if (command != null) {
throw new IllegalStateException("command != null");
}
// We don't know whether the remote side of the socket was closed or
// not until we attempt to read from it from processOneCommand. This
// shows up as a regular POLLIN event in our regular processing loop.
if (connection.isClosedByPeer()) {
connection.closeSocket();
peers.remove(pollIndex);
socketFDs.remove(pollIndex); //处理完则从fds中移除该文件描述符
}
}
} catch (Exception e) {
......
} finally {
mIsForkChild = false;
}
} else {
//处理USAP pool的事件
// Either the USAP pool event FD or a USAP reporting pipe.
// If this is the event FD the payload will be the number of USAPs removed.
// If this is a reporting pipe FD the payload will be the PID of the USAP
// that was just specialized.
long messagePayload = -1;
try {
byte[] buffer = new byte[Zygote.USAP_MANAGEMENT_MESSAGE_BYTES];
int readBytes = Os.read(pollFDs[pollIndex].fd, buffer, 0, buffer.length);
if (readBytes == Zygote.USAP_MANAGEMENT_MESSAGE_BYTES) {
DataInputStream inputStream =
new DataInputStream(new ByteArrayInputStream(buffer));
messagePayload = inputStream.readLong();
} else {
Log.e(TAG, "Incomplete read from USAP management FD of size "
+ readBytes);
continue;
}
} catch (Exception ex) {
if (pollIndex == usapPoolEventFDIndex) {
Log.e(TAG, "Failed to read from USAP pool event FD: "
+ ex.getMessage());
} else {
Log.e(TAG, "Failed to read from USAP reporting pipe: "
+ ex.getMessage());
}
continue;
}
if (pollIndex > usapPoolEventFDIndex) {
Zygote.removeUsapTableEntry((int) messagePayload);
}
usapPoolFDRead = true;
}
}
// Check to see if the USAP pool needs to be refilled.
if (usapPoolFDRead) {
int[] sessionSocketRawFDs =
socketFDs.subList(1, socketFDs.size())
.stream()
.mapToInt(fd -> fd.getInt$())
.toArray();
final Runnable command = fillUsapPool(sessionSocketRawFDs);
if (command != null) {
return command;
}
}
}
}
4.2.6 [ZygoteConnection.java] processOneCommand()
Runnable processOneCommand(ZygoteServer zygoteServer) {
...
//fork子进程
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);
if (pid == 0) {
// 子进程执行
zygoteServer.setForkChild();
//进入子进程流程,参考[4.2.7]
return handleChildProc(parsedArgs, descriptors, childPipeFd,
parsedArgs.mStartChildZygote);
} else {
//父进程执行
// In the parent. A pid < 0 indicates a failure and will be handled in handleParentProc.
handleParentProc(pid, descriptors, serverPipeFd);
return null;
}
...
}
4.2.7 [ZygoteConnection.java] handleChildProc()
private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor[] descriptors,
FileDescriptor pipeFd, boolean isZygote) {
...
if (parsedArgs.mInvokeWith != null) {
...
throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");
} else {
if (!isZygote) {
// App进程将会调用到这里,执行目标类的main()方法
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mRemainingArgs, null /* classLoader */);
} else {
return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mRemainingArgs, null /* classLoader */);
}
}
}
这一节主要是讲解Zygote的启动流程,后面会详细讲解Zygote fork子进程的过程