Zygote进程到System Server进程
上一篇文章讲到了Zygote拉起了System server进程,本文具体讲述一下,System server启动的流程。Zygote进程拉起System Server进程调用的方法是ZygoteInit.java forkSystemServer,如下:
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
);
/* 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,3011",
"--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);//设置一些属性
if (Zygote.nativeSupportsMemoryTagging()) {
/* The system server is more privileged than regular app processes, so it has async
* tag checks enabled on hardware that supports memory tagging. 系统服务比常规应用程序进程具有更大的特权,因此它在支持内存标记的硬件上启用了异步标记检查。*/
parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_ASYNC;
} else if (Zygote.nativeSupportsTaggedPointers()) {
/* Enable pointer tagging in the system server. Hardware support for this is present
* in all ARMv8 CPUs. 在系统服务中启用指针标记。 所有ARMv8 CPU中都提供对此的硬件支持。*/
parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI;
}
if (shouldProfileSystemServer()) {
parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
}
/* Request to fork the system server process 请求fork 系统服务 进程*/
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 新孵化出来的进程 pid是0*/
if (pid == 0) {
if (hasSecondZygote(abiList)) {//有第二个socket?
waitForSecondaryZygote(socketName);//等待第二个socket
}
zygoteServer.closeServerSocket();//关闭socket
return handleSystemServerProcess(parsedArgs);//获取新进程的任务
}
return null;//zygote进程,直接返回null
}
总结
main方法调用forkSystemServer来孵化system server进程,那么这个forkSystemServer方法做了什么事情呢?
- 准备参数,是一些启动system server进程需要的参数了,这里重点关注"com.android.server.SystemServer"
- 调用Zygote.java,设置一些属性值
- 调用Zygote.forkSystemServer进行孵化system server进程
- 对孵化进程结果进行处理,这里注意,得到返回值的时候,新进程已经孵化了,所以两个进程都会跑后面的程序
- 对于新进程(System Server),返回值pid是0,所以先判断是不是有其他socket需要等待,没有的话,关闭socket连接,获取新进程的任务。这个任务(Runnable)由main方法后边调用run方法执行
- 对于zygote进程,直接返回了null,这也对对应了main方法,对于zygote进程,后续是重新开启循环等待socket 客户端连接。
Zygote.java forkSystemServer
public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
ZygoteHooks.preFork();//应该是准备工作
//调用native层的方法创建进程
int pid = nativeForkSystemServer(
uid, gid, gids, runtimeFlags, rlimits,
permittedCapabilities, effectiveCapabilities);
// Set the Java Language thread priority to the default value for new apps. 将Java语言线程优先级设置为新应用程序的默认值。
Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
ZygoteHooks.postForkCommon();
return pid;
}
private static native int nativeForkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
总结
这个方法是Java世界fork进程调用的最后一个方法了,它调用native层的方法创建System server进程,并返回pid,其他没有太多的了。
接下来的工作是寻找,System Server进程被拉起来之后需要执行的任务是什么,也就是handleSystemServerProcess返回的Runnable哪里来的?ZygoteArguments.java
这个方法是用来获取System server进程接下来需要执行的任务的。先看一下,handleSystemServerProcess方法的参数哪里来的?是在ZygoteInit.java forkSystemServer方法来的。
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(String[] args) throws IllegalArgumentException {//这里的args就是上面那个args
parseArgs(args);
}
private void parseArgs(String[] args) throws IllegalArgumentException {
int curArg = 0;
boolean seenRuntimeArgs = false;
boolean expectRuntimeArgs = true;
for ( /* curArg */ ; curArg < args.length; curArg++) {//开始解析参数
String arg = args[curArg];
if (arg.equals("--")) { //没有这个
curArg++;
break;
} else if (arg.startsWith("--setuid=")) { //有这个
if (mUidSpecified) {
throw new IllegalArgumentException(
"Duplicate arg specified");
}
mUidSpecified = true;
mUid = Integer.parseInt(
arg.substring(arg.indexOf('=') + 1));
} else if (arg.startsWith("--setgid=")) { //有这个
if (mGidSpecified) {
throw new IllegalArgumentException(
"Duplicate arg specified");
}
mGidSpecified = true;
mGid = Integer.parseInt(
arg.substring(arg.indexOf('=') + 1));
} else if (arg.startsWith("--target-sdk-version=")) { //有这个
if (mTargetSdkVersionSpecified) {
throw new IllegalArgumentException(
"Duplicate target-sdk-version specified");
}
mTargetSdkVersionSpecified = true;
mTargetSdkVersion = Integer.parseInt(
arg.substring(arg.indexOf('=') + 1));
} else if (arg.equals("--runtime-args")) { //有这个
seenRuntimeArgs = true;
} else if (arg.startsWith("--runtime-flags=")) { //没有这个
mRuntimeFlags = Integer.parseInt(
arg.substring(arg.indexOf('=') + 1));
} else if (arg.startsWith("--seinfo=")) { //没有这个
//...
} else if (arg.startsWith("--capabilities=")) { //有这个
if (mCapabilitiesSpecified) {
throw new IllegalArgumentException(
"Duplicate arg specified");
}
mCapabilitiesSpecified = true;
String capString = arg.substring(arg.indexOf('=') + 1);
String[] capStrings = capString.split(",", 2);
if (capStrings.length == 1) {
mEffectiveCapabilities = Long.decode(capStrings[0]);
mPermittedCapabilities = mEffectiveCapabilities;
} else {
mPermittedCapabilities = Long.decode(capStrings[0]);
mEffectiveCapabilities = Long.decode(capStrings[1]);
}
} else if (arg.startsWith("--rlimit=")) { //没有这个
//...
} else if (arg.startsWith("--setgroups=")) { //有这个
if (mGids != null) {
throw new IllegalArgumentException(
"Duplicate arg specified");
}
String[] params = arg.substring(arg.indexOf('=') + 1).split(",");
mGids = new int[params.length];
for (int i = params.length - 1; i >= 0; i--) {
mGids[i] = Integer.parseInt(params[i]);
}
} else if (arg.equals("--invoke-with")) { //没有这个
if (mInvokeWith != null) {
throw new IllegalArgumentException(
"Duplicate arg specified");
}
try {
mInvokeWith = args[++curArg];
} catch (IndexOutOfBoundsException ex) {
throw new IllegalArgumentException(
"--invoke-with requires argument");
}
} else if (arg.startsWith("--nice-name=")) { //有这个
if (mNiceName != null) {
throw new IllegalArgumentException(
"Duplicate arg specified");
}
mNiceName = arg.substring(arg.indexOf('=') + 1);
}
//... 后面的这一长串都没有
}
//下面的代码是处理剩余的参数的,注意到 args的参数中最后只剩下 "com.android.server.SystemServer" 这一个没有处理
if (mBootCompleted) { //这个是false
if (args.length - curArg > 0) {
throw new IllegalArgumentException("Unexpected arguments after --boot-completed");
}
} else if (mAbiListQuery || mPidQuery) {//这两个是false
if (args.length - curArg > 0) {
throw new IllegalArgumentException("Unexpected arguments after --query-abi-list.");
}
} else if (mPreloadPackage != null) {//这个也没有赋值
if (args.length - curArg > 0) {
throw new IllegalArgumentException(
"Unexpected arguments after --preload-package.");
}
} else if (mPreloadApp != null) {//这个也没有赋值
if (args.length - curArg > 0) {
throw new IllegalArgumentException(
"Unexpected arguments after --preload-app.");
}
} else if (expectRuntimeArgs) {//这个是true
if (!seenRuntimeArgs) {
throw new IllegalArgumentException("Unexpected argument : " + args[curArg]);
}
mRemainingArgs = new String[args.length - curArg];//这里就把 "com.android.server.SystemServer" 参数处理了
System.arraycopy(args, curArg, mRemainingArgs, 0, mRemainingArgs.length);
}
if (mStartChildZygote) {//这个也是false
//...
}
}
总结
上面的这个ZygoteArguments类主要做参数处理。
- 将参数放到类的成员变量
- 把 "com.android.server.SystemServer" 参数 放到了 mRemainingArgs
- 需要注意一下mInvokeWith这个变量没有赋值,后面会用到
下面正式去寻找Runnable的来源
ZygoteInit.java handleSystemServerProcess
private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
// set umask to 0077 so new files and directories will default to owner-only permissions.
//将umask设置为0077,以便新文件和目录将默认为仅所有者权限。
Os.umask(S_IRWXG | S_IRWXO);
if (parsedArgs.mNiceName != null) {
Process.setArgV0(parsedArgs.mNiceName);
}
final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
if (systemServerClasspath != null) {
performSystemServerDexOpt(systemServerClasspath);
// Capturing profiles is only supported for debug or eng builds since selinux normally
// prevents it.捕获配置文件仅支持调试或eng构建,因为selinux通常会阻止它。
if (shouldProfileSystemServer() && (Build.IS_USERDEBUG || Build.IS_ENG)) {
try {
Log.d(TAG, "Preparing system server profile");
prepareSystemServerProfile(systemServerClasspath);
} catch (Exception e) {
Log.wtf(TAG, "Failed to set up system server profile", e);
}
}
}
//***说实话,前面一大堆代码干嘛的没看懂
//前面分析参数的时候,知道了这个mInvokeWith没有赋值,所以会是null
if (parsedArgs.mInvokeWith != null) {
String[] args = parsedArgs.mRemainingArgs;
// If we have a non-null system server class path, we'll have to duplicate the
// existing arguments and append the classpath to it. ART will handle the classpath
// correctly when we exec a new process.
//如果我们有一个非null的系统服务类路径,我们将必须复制现有参数并将类路径附加到该路径上。 当我们执行新进程时,ART将正确处理类路径。
if (systemServerClasspath != null) {
String[] amendedArgs = new String[args.length + 2];
amendedArgs[0] = "-cp";
amendedArgs[1] = systemServerClasspath;
System.arraycopy(args, 0, amendedArgs, 2, args.length);
args = amendedArgs;
}
WrapperInit.execApplication(parsedArgs.mInvokeWith,
parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
VMRuntime.getCurrentInstructionSet(), null, args);
throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
cl = createPathClassLoader(systemServerClasspath, parsedArgs.mTargetSdkVersion);
Thread.currentThread().setContextClassLoader(cl);
}
/*
* Pass the remaining arguments to SystemServer.
* 将其余参数传递给SystemServer。
*/
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mDisabledCompatChanges,
parsedArgs.mRemainingArgs, cl);
}
/* should never reach here */
}
总结
上面这个方法没什么好看的,只看最后返回ZygoteInit.zygoteInit的返回值,注意:parsedArgs.mRemainingArgs的值是:"com.android.server.SystemServer"
ZygoteInit.java zygoteinit
public static final Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
RuntimeInit.redirectLogStreams();
RuntimeInit.commonInit();
ZygoteInit.nativeZygoteInit();
//前面好像都是一些初始化操作
return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
classLoader);
}
总结
这个方法比较简单了,最后调用RuntimeInit.applicationInit,不多说了。注意:argv只有一个参数:"com.android.server.SystemServer"
RuntimeInit.java applicationInit
protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {
// If the application calls System.exit(), terminate the process
// immediately without running any shutdown hooks. It is not possible to
// shutdown an Android application gracefully. Among other things, the
// Android runtime shutdown hooks close the Binder driver, which can cause
// leftover running threads to crash before the process actually exits.
// 如果应用程序调用System.exit(),则在不运行任何关闭挂钩的情况下立即终止进程。 无法正常关闭Android应用程序。 其中,Android运行时关闭挂钩会关闭Binder驱动程序,这可能导致剩余的运行线程在进程实际退出之前崩溃。
nativeSetExitWithoutCleanup(true);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);//设置sdk版本
VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges);//兼容性?不太懂这句
final Arguments args = new Arguments(argv);//重新封装参数 argv只有一个参数:"com.android.server.SystemServer"
// The end of of the RuntimeInit event (see #zygoteInit).
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
// Remaining arguments are passed to the start class's static main 其余参数传递给起始类的静态main
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
总结
这个方法也简单
- 设置sdk版本
- 重新封装参数
- 找到要运行的静态类
- 重点关注一下调用findStaticMain方法的args.startClass参数
下面看一下findStaticMain方法的args.startClass参数:
static class Arguments {
/** first non-option argument */
String startClass;
/** all following arguments */
String[] startArgs;
Arguments(String args[]) throws IllegalArgumentException {
parseArgs(args);
}
/**
* Parses the commandline arguments intended for the Runtime.
*/
private void parseArgs(String args[])
throws IllegalArgumentException {
int curArg = 0;
for (; curArg < args.length; curArg++) {
String arg = args[curArg];
if (arg.equals("--")) {//没有 -- 开头的参数
curArg++;
break;
} else if (!arg.startsWith("--")) {//没有 -- 开头的参数 直接break了
break;
}
}
if (curArg == args.length) {
throw new IllegalArgumentException("Missing classname argument to RuntimeInit!");
}
startClass = args[curArg++];// 这里有一个 "com.android.server.SystemServer" 参数了
startArgs = new String[args.length - curArg];
System.arraycopy(args, curArg, startArgs, 0, startArgs.length);
}
}
总结
这个类也简单,需要注意的是:startClass的值是com.android.server.SystemServer
RuntimeInit.java findStaticMain
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
Class<?> cl;
try {
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
throw new RuntimeException(
"Missing static main on " + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException(
"Problem getting static main on " + className, ex);
}
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException(
"Main method is not public and static on " + className);
}
/*
* This throw gets caught in ZygoteInit.main(), which responds
* by invoking the exception's run() method. This arrangement
* clears up all the stack frames that were required in setting
* up the process.
*/
return new MethodAndArgsCaller(m, argv);
}
总结
这个方法也简单
- 通过反射找到需要运行的类的main方法,startClass的值是com.android.server.SystemServer,所以这里运行那个类不用多说了吧
- 创建MethodAndArgsCaller类的对象返回,MethodAndArgsCaller类实现Runnable接口,可算找到了,哈哈哈
RuntimeInit.java MethodAndArgsCaller类
static class MethodAndArgsCaller implements Runnable {
/** method to call */
private final Method mMethod;
/** argument array */
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
Throwable cause = ex.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
throw (Error) cause;
}
throw new RuntimeException(ex);
}
}
}
这个类也简单
- 实现了Runnable接口
- 在run方法中运行传递过来的方法
最终总结
整个流程走下来,其实都非常简单,最主要的是要记住参数都是来自哪里,是个什么值,这对后续的代码走哪里非常重要。到这,System Server进程就启动,而且之后的任务是执行: com.android.server.SystemServer的main方法