Android 系统启动过程(二) —— zygote 进程
1. zygote 进程概要
zygote 进程启动做了什么:
- 创建了 AppRuntime,并调用其 start 方法,启动 Zygote 进程。
- 创建 JVM,并为其注册 JNI 方法。
- 通过 JNI 调用 ZygoteInit 的 main 函数进入 Zygote 的 Java 框架层。
- 启动 SystemServer 进程。
- 创建服务器端 Socket,并通过 runSelectLoop 方法等待 AMS 的请求来创建新的应用程序进程。
本文将基于 android-14.0.0_r9
版本代码对以上内容进行详细讲解。
2. Native 层
zygote 进程是由 init 进程启动的,最初运行在 Native 层,后通过 JNI 调用 ZygoteInit 的 main 方法,从 Native 层进入了 Java 层。
2.1 init 进程启动 zygote 进程
zygote 进程是通过 init 进程启动的,那么 init 进程如何启动这个名为 zygote 的 Service?
在 zygote 的启动脚本中,以 init.zygote64.rc 为例:
# system/core/rootdir/init.zygote64.rc
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system
socket usap_pool_primary stream 660 root system
onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
...
由此可知 Zygote 的进程名为 zygote,执行程序为 app_process ,classname 为 main。
在 init.rc 文件中使用 import 引入 zygote 的启动脚本。查看 init.rc :
...
import /system/etc/init/hw/init.${ro.zygote}.rc
on late-init
...
# Now we can start zygote.
trigger zygote-start
...
...
on zygote-start
wait_for_prop odsign.verification.done 1
# A/B update verifier that marks a successful boot.
exec_start update_verifier
start statsd
start netd
start zygote
start zygote_secondary
在 late-init 阶段触发了 zygote-start,接着执行 start zygote 命令启动 zygote 进程。
通过 builtins.cpp 中 builtin_functions 可知,start 是一个 Commend,对应的函数为 builtins.cpp 中的 do_start 函数:
// init/builtins.cpp
static Result<void> do_start(const BuiltinArguments& args) {
Service* svc = ServiceList::GetInstance().FindService(args[1]);
if (!svc) return Error() << "service " << args[1] << " not found";
errno = 0;
if (auto result = svc->Start(); !result.ok()) {
return ErrorIgnoreEnoent() << "Could not start service: " << result.error();
}
return {};
}
通过 do_start 函数找到 zygote 对应的 Service,并调用其 Start 函数启动该 Service:
// system/core/init/service.cpp
Result<void> Service::Start() {
...
// Service 正在运行,不启动
if (flags_ & SVC_RUNNING) {
if ((flags_ & SVC_ONESHOT) && disabled) {
flags_ |= SVC_RESTART;
}
LOG(INFO) << "service '" << name_
<< "' requested start, but it is already running (flags: " << flags_ << ")";
// It is not an error to try to start a service that is already running.
reboot_on_failure.Disable();
return {};
}
...
pid_t pid = -1;
// 创建子进程
if (namespaces_.flags) {
pid = clone(nullptr, nullptr, namespaces_.flags | SIGCHLD, nullptr);
} else {
pid = fork();
}
// 当前代码逻辑在子线程中运行
if (pid == 0) {
umask(077);
cgroups_activated.CloseWriteFd();
setsid_finished.CloseReadFd();
// 启动 Service 子进程
RunService(descriptors, std::move(cgroups_activated), std::move(setsid_finished));
_exit(127);
} else {
cgroups_activated.CloseReadFd();
setsid_finished.CloseWriteFd();
}
...
}
在 Start 函数中,init 进程创建 zygote 子进程,在 zygote 子进程中通过 RunService 进入到 zygote 的 main 函数中:
void Service::RunService(const std::vector<Descriptor>& descriptors,
InterprocessFifo cgroups_activated, InterprocessFifo setsid_finished) {
...
if (!ExpandArgsAndExecv(args_, sigstop_)) {
PLOG(ERROR) << "cannot execv('" << args_[0]
<< "'). See the 'Debugging init' section of init's README.md for tips";
}
}
static bool ExpandArgsAndExecv(const std::vector<std::string>& args, bool sigstop) {
...
return execv(c_strings[0], c_strings.data()) == 0;
}
由 init.zygote64.rc 可知 zygote 的执行程序路径是 /system/bin/app_process64
,对应的入口文件为 /frameworks/base/cmds/app_process/app_main.cpp
:
// frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[])
{
...
// 创建 Android 运行时对象,AppRuntime 是 AndroidRuntime 的子类
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
...
while (i < argc) {
const char* arg = argv[i++];
// 如果当前运行在 zygote 进程中
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;
}
...
}
...
// 如果运行在zygote 进程中,调用 runtime 的 start 函数
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
}
...
}
如果 app_main.cpp 的 main 函数运行在 zygote 进程中,则调用 AndroidRuntime 的 start 函数。
2.2 AndroidRuntime::start
AndroidRuntime 的 start 函数调用 ZygoteInit 的 main 方法,首先看一下 AndroidRuntime 的 start 方法:
// frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
...
// 启动虚拟机
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
return;
}
onVmCreated(env);
// 为虚拟机注册 JNI 方法
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
...
// className 为 com.android.internal.os.ZygoteInit
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr);
for (size_t i = 0; i < options.size(); ++i) {
jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
assert(optionsStr != NULL);
env->SetObjectArrayElement(strArray, i + 1, optionsStr);
}
char* slashClassName = toSlashClassName(className != NULL ? className : "");
// 找到 ZygoteInit
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
// 找到 ZygoteInit 的 main 方法
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
// 通过 JNI 调用 ZygoteInit 的 main 方法
env->CallStaticVoidMethod(startClass, startMeth, strArray);
#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
...
}
AndroidRuntime::start 函数中主要进行了:
- 启动虚拟机
- 注册 JNI
- 通过 JNI 调用 ZygoteInit 的 main 方法
3. Java 层
ZygoteInit 的 main 方法是由 java 编写的,通过 JNI 调用 ZygoteInit 的 main 方法,zygote 进程从 Native 层进入了 Java 层,所以 zygote 进程可以成为称为 java 进程的鼻祖 :
// com.android.internal.os.ZygoteInit
public static void main(String[] argv) {
...
try {
...
if (!enableLazyPreload) {
...
// 1. 预加载类和资源
preload(bootTimingsTraceLog);
...
}
...
// 2. 创建 ZygoteServer,创建服务器端 Socket
zygoteServer = new ZygoteServer(isPrimaryZygote);
if (startSystemServer) {
// 3. 启动 SystemServer 进程
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
...
}
...
// 4. 死循环,等待 AMS 请求
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
...
} finally {
...
}
...
}
ZygoteInit main 方法主要做了:
- 预加载相关资源
- 创建了 ZygoteServer,创建服务器端 Socket
- 创建了 SystemServer 进程
- 执行 runSelectLoop
3.1 创建 Server 端 Socket:
// core/java/com/android/internal/os/ZygoteServer.java
ZygoteServer(boolean isPrimaryZygote) {
mUsapPoolEventFD = Zygote.getUsapPoolEventFD();
if (isPrimaryZygote) {// PRIMARY_SOCKET_NAME = "zygote"
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
mUsapPoolSocket =
Zygote.createManagedSocketFromInitSocket(
Zygote.USAP_POOL_PRIMARY_SOCKET_NAME);
} else {
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME);
mUsapPoolSocket =
Zygote.createManagedSocketFromInitSocket(
Zygote.USAP_POOL_SECONDARY_SOCKET_NAME);
}
mUsapPoolSupported = true;
fetchUsapPoolPolicyProps();
}
// core/java/com/android/internal/os/Zygote.java
static LocalServerSocket createManagedSocketFromInitSocket(String socketName) {
int fileDesc;
// 拼接 Socket 的名称,ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_",socketName = "zygote"
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;// ANDROID_SOCKET_zygote
try {
// 得到 Socket 的环境变量的值
String env = System.getenv(fullSocketName);
// 将 Socket 环境变量的值转换为文件描述符的参数
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException("Socket unset or invalid: " + fullSocketName, ex);
}
try {
// 创建文件描述符
FileDescriptor fd = new FileDescriptor();
fd.setInt$(fileDesc);
// 创建服务器端 Socket
return new LocalServerSocket(fd);
} catch (IOException ex) {
throw new RuntimeException(
"Error building socket from file descriptor: " + fileDesc, ex);
}
}
通过 LocalServerSocket 创建了服务器端的 Socket,用来等待 AMS 请求 zygote,以创建新的应用程序进程。
3.2 创建 SystemServer 进程
forkSystemServer 创建 SystemServer 进程:
// com.android.internal.os.ZygoteInit
private static Runnable forkSystemServer(String abiList, String socketName,
com.android.internal.os.ZygoteServer zygoteServer) {
...
// 创建 args 数组,用来保存启动 SystemServer 的启动参数
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,3011",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
"com.android.server.SystemServer",
};
ZygoteArguments parsedArgs;
int pid;
try {
ZygoteCommandBuffer commandBuffer = new ZygoteCommandBuffer(args);
try {
parsedArgs = ZygoteArguments.getInstance(commandBuffer);
} catch (EOFException e) {
throw new AssertionError("Unexpected argument error for forking system server", e);
}
commandBuffer.close();
Zygote.applyDebuggerSystemProperty(parsedArgs);
Zygote.applyInvokeWithSystemProperty(parsedArgs);
...
/* Request to fork the system server process */
// 创建子进程 SystemServer
pid = Zygote.forkSystemServer(
parsedArgs.mUid, parsedArgs.mGid,
parsedArgs.mGids,
parsedArgs.mRuntimeFlags,
null,
parsedArgs.mPermittedCapabilities,
parsedArgs.mEffectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
// 当前代码运行在子线程中
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
zygoteServer.closeServerSocket();
// 处理 SystemServer 进程
return handleSystemServerProcess(parsedArgs);
}
return null;
}
forkSystemServer 内部调用 nativeForkSystemServer 方法,通过 fork 函数在当前进程创建 SystemServer 进程:
// core/java/com/android/internal/os/Zygote.java
static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
ZygoteHooks.preFork();
int pid = nativeForkSystemServer(
uid, gid, gids, runtimeFlags, rlimits,
permittedCapabilities, effectiveCapabilities);
// Set the Java Language thread priority to the default value for new apps.
Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
ZygoteHooks.postForkCommon();
return pid;
}
具体有关 SystemServer 进程的内容在 SystemServer 进程的启动流程中进行详细分析。
3.3 死循环等待 AMS 请求
Zygote 进程将 SystemServer 进程启动后,就会在在这个服务端的 Socket 上等待 AMS 请求 Zygote 进程来创建新的应用程序进程。
执行 runSelectLoop,循环等待 AMS 请求:
// core/java/com/android/internal/os/ZygoteServer.java
Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> socketFDs = new ArrayList<>();
ArrayList<ZygoteConnection> peers = new ArrayList<>();
// mZygoteSocket 为 createManagedSocketFromInitSocket 创建的服务端 Socket,获得该 Socket 的 fd 字段的值并添加到 fd 列表中
socketFDs.add(mZygoteSocket.getFileDescriptor());
peers.add(null);
mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
// 循环等待 AMS 请求 Zygote 进程创建新的应用程序
while (true) {
...
int pollIndex = 0;
// 通过遍历将 socketFDs 存储的信息转移到 pollFDs 中
for (FileDescriptor socketFD : socketFDs) {
pollFDs[pollIndex] = new StructPollfd();
pollFDs[pollIndex].fd = socketFD;
pollFDs[pollIndex].events = (short) POLLIN;
++pollIndex;
}
...
int pollReturnValue;
try {
// 处理轮询状态,当pollFDs有事件到来则往下执行,否则阻塞在这里
pollReturnValue = Os.poll(pollFDs, pollTimeoutMs);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
if (pollReturnValue == 0) {
...
} else {
boolean usapPoolFDRead = false;
// 优先处理已建立连接的信息
while (--pollIndex >= 0) {
// 接收到请求继续执行,否则tao
if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
continue;
}
if (pollIndex == 0) {
// Zygote server socket
// 得到 ZygoteConnection 添加到 Socket 的连接列表 peers 中
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
// 将 ZygoteConnection 的 fd 添加到 socketFDs 中,以便可以接收到 AMS 发送过来的请求。
socketFDs.add(newPeer.getFileDescriptor());
} else if (pollIndex < usapPoolEventFDIndex) {// pollIndex 不为 0
// Session socket accepted from the Zygote server socket
try {
// 创建一个新的应用进程
ZygoteConnection connection = peers.get(pollIndex);
boolean multipleForksOK = !isUsapPoolEnabled()
&& ZygoteHooks.isIndefiniteThreadSuspensionSafe();
final Runnable command =
connection.processCommand(this, multipleForksOK);
// TODO (chriswailes): Is this extra check necessary?
if (mIsForkChild) {
...
return command;
} else {
...
if (connection.isClosedByPeer()) {
// 清除相关信息
connection.closeSocket();
peers.remove(pollIndex);
socketFDs.remove(pollIndex);
}
}
}
...
}
当 AMS 的请求数据到来时,会调用 ZygoteConnection 的 processCommand 方法:
// java/com/android/internal/os/ZygoteConnection.java
Runnable processCommand(ZygoteServer zygoteServer, boolean multipleOK) {
ZygoteArguments parsedArgs;
try (ZygoteCommandBuffer argBuffer = new ZygoteCommandBuffer(mSocket)) {
while (true) {
try {
parsedArgs = ZygoteArguments.getInstance(argBuffer);
// Keep argBuffer around, since we need it to fork.
}
...
if (parsedArgs.mInvokeWith != null || parsedArgs.mStartChildZygote
|| !multipleOK || peer.getUid() != Process.SYSTEM_UID) {
// 创建应用程序进程
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.mIsTopApp, parsedArgs.mPkgDataInfoList,
parsedArgs.mAllowlistedDataInfoList, parsedArgs.mBindMountAppDataDirs,
parsedArgs.mBindMountAppStorageDirs);
try {
// 当前代码逻辑运行在子进程中
if (pid == 0) {
// in child
// pid == 0 表示创建成功,则进入子进程中,即应用程序进程
zygoteServer.setForkChild();
zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
// 处理应用程序进程,进入子进程执行相关操作
return handleChildProc(parsedArgs, childPipeFd,
parsedArgs.mStartChildZygote);
} else {
// In the parent. A pid < 0 indicates a failure and will be handled in
// handleParentProc.
// pid < 0表示创建失败,则进入父进程返回消息给Client Socket表示启动失败
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
handleParentProc(pid, serverPipeFd);
return null;
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}
...
}
}
...
}
调用 Zygote 的 forkAndSpecialize 方法来创建应用程序进程,参数为 parsedArgs 中存储的应用进程启动参数,返回值为 pid。forkAndSpecialize 方法通过 fork 当前进程来创建一个子进程,如果 pid = 0,则说明当前代码逻辑运行在新创建的子进程(应用程序进程)中,这时会调用 handleParentProc 方法来处理应用程序进程。
本文主要讲解 zygote 进程的启动过程,具体的应用程序启动过程不在本文进行过多介绍,相关内容会在应用程序启动过程文章中进行详细描述。
到此 zygote 进程就介绍完了,接下来我们看看 SystemServer 进程。
转载自:https://juejin.cn/post/7384617995874009125