一、写在前面
接上篇Android Zygote进程启动源码继续对SystemServer进程启动源码进行分析。
二、Zygote进程fork SystemServer进程
1、ZygoteInit.forkSystemServer
如下代码位于ZygoteInit中,主要就是fork SystemServer前的一些参数准备以及fork成功之后的处理,整体理解不难。
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
//用于指定新进程应该具有的能力集合,以限制进程的权限并增强系统的安全性
//具体的常量值定义于文件:bionic/libc/kernel/uapi/linux/capability.h中
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 &= Integer.toUnsignedLong(data[0].effective) |
(Integer.toUnsignedLong(data[1].effective) << 32);
//进程启动参数,比如uid、gid以及进程入口类等
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,3005,3006,3007,3009,3010,3011,3012",
"--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();
//启用JDWP调试
//JDWP是一种用于远程调试Java虚拟机的协议,它可以让开发人员在运行中的应用程序中设置断点、监视变量和调试代码
Zygote.applyDebuggerSystemProperty(parsedArgs);
//指定应用程序进程启动时要使用的可执行文件路径
Zygote.applyInvokeWithSystemProperty(parsedArgs);
......
//systemServer进程是否开启性能分析
if (shouldProfileSystemServer()) {
parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
}
//开始fork systemServer进程
pid = Zygote.forkSystemServer(
parsedArgs.mUid, parsedArgs.mGid,
parsedArgs.mGids,
parsedArgs.mRuntimeFlags,
null,
parsedArgs.mPermittedCapabilities,
parsedArgs.mEffectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
//表示fork成功,并且当前处于SystemServer进程中
if (pid == 0) {
//首先判断当前设备是否存在两个Zygote进程,一般情况下不会出现
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
//关闭父进程zygote复制而来的LocalSocketServer
zygoteServer.closeServerSocket();
return handleSystemServerProcess(parsedArgs);
}
return null;
}
2、forkSystemServer
如下最终调用到native层(native层相关讲解可参考:Android系统启动-SystemServer上篇)去执行子进程的fork操作。不过在调用到native之前需要停止Zygote进程中所有守护线程以及相关子线程。
对于为什么需要停止所有子线程如下是来源于chatGpt的回答:在 fork 子进程时,子进程会继承父进程的状态,包括线程、文件描述符、内存映射等。如果 Zygote 进程是多线程的,子进程会继承多个线程的状态,这可能会导致子进程状态混乱,影响应用程序的正确运行。
static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
//停止守护线程:HeapTaskDaemon、ReferenceQueueDaemon、FinalizerDaemon和FinalizerWatchdogDaemon
//等待所有线程结束:读取文件proc/self/task以判断当前是否只有一个线程,如果不是则通过yield函数让出时间片等待其他线程执行结束
ZygoteHooks.preFork();
//调用到native层以执行子进程fork操作
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;
}
三、fork SystemServer进程成功
1、handleSystemServerProcess
如下代码做了几件事情:设置SystemServer进程创建文件的访问权限、设置进程名、根据SystemServer所在dex文件创建ClassLoader,并最终调用到函数ZygoteInit.zygoteInit中。
private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
//设置SystemServer进程新创建文件权限为0077,即仅仅授予文件所有者读、写以及可执行权限
Os.umask(S_IRWXG | S_IRWXO);
//指定当前进程名为:system_server
if (parsedArgs.mNiceName != null) {
Process.setArgV0(parsedArgs.mNiceName);
}
final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
if (systemServerClasspath != null) {
if (shouldProfileSystemServer() && (Build.IS_USERDEBUG || Build.IS_ENG)) {
......
//非release版本执行
}
}
//mInvokeWith对应于参数--invoke-with,但从上述分析来看启动SystemServer并没有携带该参数,因此为null
if (parsedArgs.mInvokeWith != null) {
String[] args = parsedArgs.mRemainingArgs;
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
ClassLoader cl = getOrCreateSystemServerClassLoader();
if (cl != null) {
Thread.currentThread().setContextClassLoader(cl);
}
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mDisabledCompatChanges,
parsedArgs.mRemainingArgs, cl);
}
/* should never reach here */
}
2、zygoteInit
如下代码主要做一些进程相关的初始化工作。比如日志重定向、全局异常捕获handler设置、重置log配置以及启动Binder线程池等。
public static 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");
//重定向log输出
//将System.out和System.err日志输出重定向到Log.INFO和Log.WARN
RuntimeInit.redirectLogStreams();
//一些初始化相关动作,比如设置默认的全局异常捕获handler、时区设置、重置log配置、设置默认的HTTP User-Agent以及设置socket tag以进行流量统计
RuntimeInit.commonInit();
//zygote初始化,用于启动binder线程池
ZygoteInit.nativeZygoteInit();
//通过反射获取当前进程入口类及main函数
return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
classLoader);
}
3、binder线程池启动
全局搜索nativeZygoteInit
,其对应native实现定义在AndroidRuntime.cpp中。代码如下:
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}
上述代码onZygoteInit
函数直接通过链接点击进去发现是一个virtual函数,因此再次全局搜索onZygoteInit
函数定义,最终app_main.cpp中找到其实现。代码如下:
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
//启动binder线程chi
proc->startThreadPool();
}
4、applicationInit
如下代码也是为了做一些初始化工作。整体代码很简单。
protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {
//设置SystemServer进程退出时不清理资源
//如果为false表示需要清理资源,例如释放内存、关闭文件句柄等等,然后再退出进程
nativeSetExitWithoutCleanup(true);
//设置当前的SDK版本
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
//应用程序的兼容性限制是指针对特定版本的Android系统或者特定设备的功能限制
//设置Android虚拟机运行时的兼容性限制,确保应用程序能够在不同的Android系统和设备上正常运行
VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges);
final Arguments args = new Arguments(argv);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//通过反射查找到类com.android.server.SystemServer的main函数
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
5、findStaticMain
如下代码就更简单了,就是通过上述创建的ClassLoader找到com.android.server.SystemServer
的main
函数,并返回一个Runnable
的子类MethodAndArgsCaller
以返回到ZygoteInit.main中进行调用。
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
Class<?> cl;
try {
//通过上述创建的Classloader查找到类com.android.server.SystemServer
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
//查找类com.android.server.SystemServer中的main函数
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.
*/
//返回一个Runnable的子类给到ZygoteInit的main函数进行调用
return new MethodAndArgsCaller(m, argv);
}
6、MethodAndArgsCaller
如下是MethodAndArgsCaller函数的定义及实现。
static class MethodAndArgsCaller implements Runnable {
private final Method mMethod;
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);
}
}
}
四、SystemServer
后续就正式进入到SystemServer进程的执行流程,以启动Android各种系统服务。
1、main
该函数很简单,就是创建一个SystemServer对象并调用其run函数。
public static void main(String[] args) {
new SystemServer().run();
}
2、run
run函数就复杂太多太多了,如下只给出启动系统服务以及loop相关代码
private void run() {
TimingsTraceAndSlog t = new TimingsTraceAndSlog();
......
// Start services.
try {
t.traceBegin("StartServices");
//启动关键服务吗,比如FileIntegrityService、Installer、DeviceIdentifiersPolicyService等
startBootstrapServices(t);
//启动核心服务,比如SystemConfigService、BatteryService、UsageStatsService等
startCoreServices(t);
//启动其他服务,比如KeyChainSystemService、BinaryTransparencyService、DeviceStateManagerService等
startOtherServices(t);
//启动Apex相关services,ApexPackageService
startApexServices(t);
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
t.traceEnd(); // StartServices
}
......
// Loop forever.
//防止进程退出,因此该处无限循环
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
五、总结
如上即为SystemServer从Zygote进程启动的源码大体流程。