更多 Android Framework 相关教程:yuandaimaahao.gitee.io/androidfram...
上节讲到 Zygote 进程的初始化过程将转到 Java 层,开始执行 ZygoteInit 的 main 函数了.
main 函数很长,我们分步查看:
java
@UnsupportedAppUsage
public static void main(String argv[]) {
ZygoteServer zygoteServer = null;
// Mark zygote start. This ensures that thread creation will throw
// an error.
// 调用此方法后,虚拟机会拒绝线程的创建,如果此时创建会产生错误
ZygoteHooks.startZygoteNoThreadCreation();
调用 startZygoteNoThreadCreation()
方法后,会设置一个标志位,此时运行时(虚拟机)会拒绝线程的创建,如果此时创建会产生错误。
接着往下看 main 函数:
java
// Zygote goes into its own process group.
// 设置进程的 group id
try {
Os.setpgid(0, 0);
} catch (ErrnoException ex) {
throw new RuntimeException("Failed to setpgid(0,0)", ex);
}
Runnable caller;
try {
// 记录一些时间信息,用于性能分析,和主要功能无关
// Report Zygote start time to tron unless it is a runtime restart
if (!"1".equals(SystemProperties.get("sys.boot_completed"))) {
MetricsLogger.histogram(null, "boot_zygote_init",
(int) SystemClock.elapsedRealtime());
}
// 记录 trace 信息
String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";
TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,
Trace.TRACE_TAG_DALVIK);
bootTimingsTraceLog.traceBegin("ZygoteInit");
// 启动DDMS虚拟机监控调试服务
RuntimeInit.enableDdms();
这里主要是设置进程 groupid,记录一些时间和 trace 信息, 启动 DDMS 虚拟机监控调试服务,这些东西都是服务于程序的性能分析,与主要流程无关。
接着往下看 main 函数:
java
// 参数解析
boolean startSystemServer = false;
String zygoteSocketName = "zygote";
String abiList = null;
boolean enableLazyPreload = false;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
// 开启系统服务
startSystemServer = true;
} else if ("--enable-lazy-preload".equals(argv[i])) {
// 启动延迟加载
enableLazyPreload = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) {
// abi 类型,一个 CPU 对应一个 abi
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
// 解析 socket name
zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
// 未知参数会抛出异常
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);
// 没有指定 ABI 参数会抛出异常
if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
}
// In some configurations, we avoid preloading resources and classes eagerly.
// In such cases, we will preload things prior to our first fork.
if (!enableLazyPreload) {
bootTimingsTraceLog.traceBegin("ZygotePreload");
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
preload(bootTimingsTraceLog);
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
bootTimingsTraceLog.traceEnd(); // ZygotePreload
} else {
Zygote.resetNicePriority();
}
// Do an initial gc to clean up after startup
bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
gcAndFinalize();
bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC
bootTimingsTraceLog.traceEnd(); // ZygoteInit
// Disable tracing so that forked processes do not inherit stale tracing tags from
// Zygote.
Trace.setTracingEnabled(false, 0);
- 解析出参数
- 参数不正确,直接排除异常
- trace 相关的记录,用于程序的分析
接着往下看 main 函数:
java
// 一些与安全相关的初始化操作
Zygote.initNativeState(isPrimaryZygote);
// 呼应前面的startZygoteNoThreadCreation()方法
// 通知虚拟机,现在可以在 zygote 进程中创建线程了
ZygoteHooks.stopZygoteNoThreadCreation();
// 初始化 Zygote 服务管理类,用来注册 socket 监听
zygoteServer = new ZygoteServer(isPrimaryZygote);
if (startSystemServer) {
// fork SystemServer
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
// 如果 r 为空,说明是 zygote 进程,不做任何处理,继续执行
if (r != null) {
// r 不为空,说明是孵化的子进程 systemserver,启动后直接返回
r.run();
return;
}
}
- 执行一些与安全相关的初始化操作
- 通知虚拟机,现在可以在 zygote 进程中创建线程了
- 初始化 Zygote 服务管理类
- 调用
forkSystemServer
方法,创建SystemServer
进程
我们重点看看 forkSystemServer
的实现。
看之前先简单了解一下 linux 中的 fork 系统调用:
- fork 会产生和当前进程完全一样的新进程
- 在 fork 函数调用后
- 新的进程将启动
- 并和当前进程一起从 fork 函数返回
- 关于 fork 的返回值
- 新的进程返回 0
- 当前进程返回新进程的 pid
看个例子:
cpp
int main()
{
pid_t fpid; //fpid 用于保存 fork 函数返回的值
int count = 0;
fpid = fork();
if (fpid < 0) {
printf("error in fork!");
}
else if (fpid == 0) {
printf("我是子进程,我的 pid 是 %d/n", getpid());
count++;
} else {
printf("我是父进程,我的 pid 是 %d/n", getpid());
count++;
}
printf("统计结果是: %d/n", count);
return 0;
}
有了上面的基础知识,我们就可以来看 forkSystemServer
方法的具体实现了:
java
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
);
/* Containers run without some capabilities, so drop any caps that are not available. */
StructCapUserHeader header = new StructCapUserHeader(
OsConstants._LINUX_CAPABILITY_VERSION_3, 0);
StructCapUserData[] data;
try {
data = Os.capget(header);
} catch (ErrnoException ex) {
throw new RuntimeException("Failed to capget()", ex);
}
capabilities &= ((long) data[0].effective) | (((long) data[1].effective) << 32);
/* 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 {
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;
}
/* 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);
}
/* For child process */
if (pid == 0) { // 子进程
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
zygoteServer.closeServerSocket();
return handleSystemServerProcess(parsedArgs);
}
return null;
}
准备好参数,然后接着调用 Zygote.forkSystemServer
:
cpp
public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
ZygoteHooks.preFork();
// Resets nice priority for zygote process.
resetNicePriority();
int pid = nativeForkSystemServer(
uid, gid, gids, runtimeFlags, rlimits,
permittedCapabilities, effectiveCapabilities);
// Enable tracing as soon as we enter the system_server.
if (pid == 0) {
Trace.setTracingEnabled(true, runtimeFlags);
}
ZygoteHooks.postForkCommon();
return pid;
}
private static native int nativeForkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
这里进一步调用 nativeForkSystemServer
native 方法,其对应的 JNI 方法如下:
cpp
static jint com_android_internal_os_Zygote_nativeForkSystemServer(
JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities,
jlong effective_capabilities) {
std::vector<int> fds_to_close(MakeUsapPipeReadFDVector()),
fds_to_ignore(fds_to_close);
fds_to_close.push_back(gUsapPoolSocketFD);
if (gUsapPoolEventFD != -1) {
fds_to_close.push_back(gUsapPoolEventFD);
fds_to_ignore.push_back(gUsapPoolEventFD);
}
// ForkCommon 对 fork 进程了包装,针对 Android 平台各个进程的共性最同意的初始化操作
pid_t pid = ForkCommon(env, true,
fds_to_close,
fds_to_ignore);
if (pid == 0) {
SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits,
permitted_capabilities, effective_capabilities,
MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true,
false, nullptr, nullptr);
} else if (pid > 0) {
// The zygote process checks whether the child process has died or not.
ALOGI("System server process %d has been created", pid);
gSystemServerPid = pid;
// There is a slight window that the system server process has crashed
// but it went unnoticed because we haven't published its pid yet. So
// we recheck here just to make sure that all is well.
int status;
if (waitpid(pid, &status, WNOHANG) == pid) {
ALOGE("System server process %d has died. Restarting Zygote!", pid);
RuntimeAbort(env, __LINE__, "System server process has died. Restarting Zygote!");
}
if (UsePerAppMemcg()) {
// Assign system_server to the correct memory cgroup.
// Not all devices mount memcg so check if it is mounted first
// to avoid unnecessarily printing errors and denials in the logs.
if (!SetTaskProfiles(pid, std::vector<std::string>{"SystemMemoryProcess"})) {
ALOGE("couldn't add process %d into system memcg group", pid);
}
}
}
return pid;
}
ForkCommon 对 fork 进程了包装,针对 Android 平台各个进程的共性做了统一的初始化操作。
从这里可以看出 Zygote.forkSystemServer
实际是对 Native 层的 fork 调用的包装,用于启动一个 SystemServer 进程。
我们回到 private static Runnable forkSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
函数中:
java
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
//......
try {
// ......
// 执行完后会产生两个进程:zygote 和 systemserver ,两个进程同时开始执行,但是进程收到的 pid是不一样的
pid = Zygote.forkSystemServer(
parsedArgs.mUid, parsedArgs.mGid,
parsedArgs.mGids,
parsedArgs.mRuntimeFlags,
null,
parsedArgs.mPermittedCapabilities,
parsedArgs.mEffectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
if (pid == 0) { // pid 等于 0,表示是子进程 SystemServer
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
// 子进程不需要 Socket 服务
zygoteServer.closeServerSocket();
// 通过反射找到SystemServer的main函数
// 并包装到Runnable的run函数中
return handleSystemServerProcess(parsedArgs);
}
return null;
}
// main 函数部分
if (startSystemServer) {
// fork SystemServer
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
// 如果 r 为空,说明是 zygote 进程,不做任何处理,继续执行
if (r != null) {
// r 不为空,说明是孵化的子进程 systemserver,启动后直接返回
r.run();
return;
}
}
这里调用 forkSystemServer 方法,完成新进程的创建,执行完后会产生两个进程:zygote 和 systemserver ,两个进程同时开始执行,但是进程收到的 pid是不一样的。对于子进程 (返回的 pid 值为 0)接下来会关闭 Socket 服务,然后通过反射找到 SystemServer 的 main 函数并包装到 Runnable 的 run 函数中返回给主函数。主函数调用 run 执行 SystemServer 的 main 函数。
接着 Zygote 进程继续执行剩下的 main 函数:
java
Log.i(TAG, "Accepting command socket connections");
// The select loop returns early in the child process after a fork and
// loops forever in the zygote.
// 这部分是在zygote进程中执行
// 此处进入一个无限循环中,处理zygote socket接收到数据
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
// 请留意这部分,主要是给子进程用的
// 子进程中是不需要在有zygote服务的
// 所以这里的关闭理论上是为了在子进程中关闭无用的zygote服务
if (zygoteServer != null) {
zygoteServer.closeServerSocket();
}
}
// We're in the child process and have exited the select loop. Proceed to execute the
// command.
if (caller != null) {
caller.run();
}
}
这里会调用 zygoteServer.runSelectLoop
进入一个无限循环中,处理 zygote socket 接收到数据,这部分主要用于启动新的进程,具体细节我们会在下一节来讲。这里我们知道 runSelectLoop 方法 fork 一个新进程,然后在新进程中把 java main 函数包装为一个 runnable 对象然后返回。接在新进程中执行 zygoteServer.closeServerSocket
来关闭 socket 服务,最后调用 caller.run()
来执行新进程的主函数