百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

Android 开机启动流程分析(12)SystemServer启动分析

haoteby 2025-07-27 20:04 16 浏览

本章关键点总结 & 说明:

这里因为整体的导图太大,因此截取一部分 ,方便大家看的清楚:

同时,下面的图是开机启动流程分析 持续迭代的效果,可放大观看。

说明:思维导图是基于之前文章不断迭代的,本章内容我们关注"启动SystemServer ->SS"部分即可

1 SS创建

1.1 SS fork进程

SystemServer的进程名实际上叫system_server(后简称为SS)。SS是由Zygote通过Zygote.forkSystemServer函数fork诞生出来的。forkSystemServer的实现(java部分)代码如下:

C++
public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
VM_HOOKS.preFork();
/**
nativeForkSystemServer{java->native调用关联}
->com_android_internal_os_Zygote_nativeForkSystemServer//接下来关键分析该方法
*/
int pid = nativeForkSystemServer(
uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
VM_HOOKS.postForkCommon();
return pid;
}

native层对应实现方法com_android_internal_os_Zygote_nativeForkSystemServer,代码如下:

C++
static jint com_android_internal_os_Zygote_nativeForkSystemServer(JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
jint debug_flags, jobjectArray rlimits, jlong permittedCapabilities,jlong effectiveCapabilities) {
//根据传递的参数,fork一个子进程
pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,debug_flags, rlimits,permittedCapabilities, effectiveCapabilities,
MOUNT_EXTERNAL_NONE, NULL, NULL, true, NULL,NULL, NULL);
if (pid > 0) {
gSystemServerPid = pid; //保存system_server的进程id
int status;
if (waitpid(pid, &status, WNOHANG) == pid) { //函数退出前须先检查刚创建的子进程是否退出了
RuntimeAbort(env); //如果system_server退出了,Zygote直接干掉了自己
}
}
return pid;
}

继续分析ForkAndSpecializeCommon,实现如下:

C++
static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid,...) {
uint64_t start = MsTime();
/**
SetSigChldHandler
->sigaction(SIGCHLD, &sa, NULL);//设置信号处理函数sigchldHandler
{该信号是子进程死亡的信号,进程死亡会执行对应的信号处理函数}
-->sigchldHandler处理信号{
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
...
if (pid == gSystemServerPid) {//如果死去的子进程是SS,则Zygote把自己也杀死了
kill(getpid(), SIGKILL);
}
}
}
*/
SetSigChldHandler();
ckTime(start, "ForkAndSpecializeCommon:SetSigChldHandler");
pid_t pid = fork();
if (pid == 0) {//子进程初始化操作
//对子进程要根据传入的参数做一些处理,例如设置进程名,设置各种id(用户id,组id等)
...
} else if (pid > 0) {
//父进程相关操作
...
}
return pid;//注意,这里也意味着有两个返回值
}

1.2 SystemServer创建过程

SS创建后,便和生父Zygote分开处理,它有了自己的历史使命。
startSystemServer中在子进程SS中最关键调用为handleSystemServerProcess来承担自己的职责。代码实现如下:

Java
//startSystemServer->handleSystemServerProcess
private static void handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) throws ZygoteInit.MethodAndArgsCaller {
closeServerSocket();//因为当前已经不是运行在zygote进程里了,所以zygote里的那个监听socket就应该关闭了
// set umask to 0077 so new files and directories will default to owner-only permissions.
Os.umask(S_IRWXG | S_IRWXO);
if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName);//设置进程名为niceName,也就是"system_server"
}
final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
if (systemServerClasspath != null) {
performSystemServerDexOpt(systemServerClasspath);
}
if (parsedArgs.invokeWith != null) {
String[] args = parsedArgs.remainingArgs;
if (systemServerClasspath != null) {
String[] amendedArgs = new String[args.length + 2];
amendedArgs[0] = "-cp";
amendedArgs[1] = systemServerClasspath;
System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
}
//设置SS进程的一些参数
WrapperInit.execApplication(parsedArgs.invokeWith,parsedArgs.niceName, parsedArgs.targetSdkVersion,null, args);
} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader());
Thread.currentThread().setContextClassLoader(cl);
}
//调用ZygoteInit函数
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}
}

SS走到RuntimeInit了,它的代码实现如下所示:

Java
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
redirectLogStreams();//重定向Log输出流。
commonInit();//做一些常规初始化。{时区,网络,日志}
nativeZygoteInit();//native层的初始化,关键点1
applicationInit(targetSdkVersion, argv, classLoader);//应用初始化,关键点2
}

1.2.1 nativeZygoteInit的调用栈,代码实现如下:

C++
/**
nativeZygoteInit{java->native调用关联}
->com_android_internal_os_RuntimeInit_nativeZygoteInit
-->gCurRuntime->onZygoteInit();//app_process的main函数中的runtime
{gCurRuntime类型为AppRuntime,由于SS是从Zygote fork出来的,所以它拥有Zygote进程的gCurRuntime}
{AppRuntime继承AndroidRuntime,初始化时会执行gCurRuntime = this;的操作,即gCurRuntime被设置为AndroidRuntime对象自己}
*/

分析gCurRuntime->onZygoteInit()的实现(定要在App_main.cpp中)如下:

C++
virtual void onZygoteInit()
{
//这些和Binder有关系
sp<ProcessState> proc = ProcessState::self();
proc->startThreadPool();/启动一个线程,用于Binder通信。
}

SS调用zygoteInitNative后,将和Binder通信系统建立联系,这样SS就能够使用Binder了。
1.2.2 applicationInit的分析,代码实现如下:

Java
private static void applicationInit(int targetSdkVersion, 
String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
nativeSetExitWithoutCleanup(true);
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
final Arguments args;
args = new Arguments(argv);
...//异常处理
//这里注意:startClass名为"com.android.server.SystemServer"
invokeStaticMain(args.startClass,args.startArgs, classLoader);
}

这里分析关键代码invokeStaticMain,实现如下:

Java
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller {
//注意我们的参数,className为"com.android.server.SystemServer"
Class<?> cl = Class.forName(className, true, classLoader);
...//异常处理
//找到com.android.server.SystemServer类的main函数,肯定有地方要调用它
Method m; 
m = cl.getMethod("main", new Class[] { String[].class });

int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException("Main method is not public and static on " + className);
}
//抛出一个异常,为什么不在这里直接调用上面的main函数呢?后面会给出答案
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}

invokeStaticMain竟然抛出了一个异常,它是在ZygoteInit的main函数中截获。

代码如下(注意:我们所在的进程是system_server):

Java
 ... 
//接着ZygoteInit中第5个关键点继续分析
...
if (startSystemServer) { //我们传入的参数满足if分支,这里是可能抛出异常的
startSystemServer(abiList, socketName);//该方法最后抛出一个异常MethodAndArgsCaller
}
...
} catch (MethodAndArgsCaller caller) {
/**
caller的run方法
mMethod.invoke(null, new Object[] { mArgs });
{mMethod为com.android.server.SystemServer的main函数}
{抛出的这个异常最后会导致com.android.server.SystemServer类的main函数被调用}
*/
caller.run(); //关键点5,被截获,调用caller的run函数
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}

说明:

父进程Zygote在fork动作后,会退出startSystemServer()函数,并走到runSelectLoop(),从而进入一种循环监听状态,每当AMS向它发出“启动新应用进程”的命令时,它又会fork一个子进程,并在子进程里抛出一个异常,这样还是会跳转到catch这里。

fork出的SystemServer进程在跳转到catch语句后,会执行SystemServer类的main()函数,而其他情况下,fork出的应用进程在跳转的catch语句后,则会执行ActivityThread类的main()函数。这个ActivityThread对于应用程序而言非常重要

为什么不在invokeStaticMain那里直接调用,而是采用这种抛异常的方式?这是因为:这个调用是在ZygoteInit.main中,相当于Native的main函数,即入口函数,位于堆栈的顶层。如果不采用抛异常的方式,而是在invokeStaticMain那里调用,则会浪费之前函数调用所占用的一些调用堆栈。这是从效率上来考虑的(由于是系统层的设计,一点点的效率都不可以忽视)

整个过程目的:ZygoteInit分裂产生的SS,其实就是为了调用com.android.server.SystemServer的main函数。

2 SS启动

这里直接查看run的实现,代码如下:

C++
//main->new SystemServer().run();
private void run() {
...// 检测时间设置
...// 启动性能分析采样
...
// Within the system server, it is an error to access Environment paths without explicitly specifying a user.
Environment.setUserRequired(true);
// Ensure binder calls into the system always run at foreground priority.
BinderInternal.disableBackgroundScheduling(true);
// Prepare the main looper thread (this thread).
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_FOREGROUND);
...
Looper.prepareMainLooper(); //准备主线程循环
// Initialize native services.
System.loadLibrary("android_servers"); //加载libandroid_servers.so,源码在framework/base/services/jni下。
nativeInit();//调用native函数,关键点1
...
performPendingShutdown();// Check whether we failed to shut down last time we tried.This call may not return.
createSystemContext();//初始化系统上下文,关键点2
// Create the system service manager.
mSystemServiceManager = new SystemServiceManager(mSystemContext);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// 启动服务
try {
startBootstrapServices();//启动BootStrap相关服务,关键点3
startCoreServices();//启动核心服务,关键点4
startOtherServices();//启动其他服务,关键点5
} catch (Throwable ex) { /// M: RecoveryManagerService @{
if (mRecoveryManagerService != null && ex instanceof RuntimeException) {
mRecoveryManagerService.handleException((RuntimeException)ex, true);
}
}
...
addBootEvent(new String("Android:SysServerInit_END"));
// Loop forever.
Looper.loop();// 启动线程循环,等待消息处理
throw new RuntimeException("Main thread loop unexpectedly exited");//不应该执行到这里
}

2.1 native_init调用栈如下:

C++
/**
nativeInit{java->native调用关联}
->android_server_SystemServer_nativeInit
-->property_get("system_init.startsensorservice", propBuf, "1");
-->if (strcmp(propBuf, "1") == 0){SensorService::instantiate();}
{通过属性确定SensorService是否启动}
*/

2.2 关注createSystemContext,代码实现如下:

Java
private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
}

这里主要就是初始化mSystemContext成员变量。


2.3 启动各种各样的服务
2.3.1 startBootstrapServices();

//引导服务,使系统可以正常工作的必要服务,这些服务具有复杂的相互依赖性

Java
private void startBootstrapServices() {
//服务必须提前加载的原因
//installd完成启动它才有一个机会用适当的方法创建关键的目录,如数据/用户权限。
Installer installer = mSystemServiceManager.startService(Installer.class);
//AMS是核心显示相关
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
mActivityManagerService.setInstaller(installer);
//PowerMS很多服务需要使用它,被native daemon监听并很快处理binder回调
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
//AMS关联PowerMS
mActivityManagerService.initPowerManagement();
//为PackageMS初始化准备
mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
// Only run "core" apps if we're encrypting the device.
String cryptState = SystemProperties.get("vold.decrypt");
if (ENCRYPTING_STATE.equals(cryptState)) {
Slog.w(TAG, "Detected encryption in progress - only parsing core apps");
mOnlyCore = true;
} else if (ENCRYPTED_STATE.equals(cryptState)) {
Slog.w(TAG, "Device encrypted - only parsing core apps");
mOnlyCore = true;
}
//PackageMS启动初始化
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
mFirstBoot = mPackageManagerService.isFirstBoot();
mPackageManager = mSystemContext.getPackageManager();
ServiceManager.addService(Context.USER_SERVICE, UserManagerService.getInstance());
//用attribute cache来初始化packages的cache resources
AttributeCache.init(mSystemContext);
//为系统进程设置应用程序实例且启动
mActivityManagerService.setSystemProcess();
}

2.3.2 startCoreServices();

//核心服务,启动一些不在引导过程中的一些基本服务。

Java
private void startCoreServices() {
// Manages LEDs and display backlight.
mSystemServiceManager.startService(LightsService.class);
// Tracks the battery level. Requires LightService.
mSystemServiceManager.startService(BatteryService.class);
// Tracks application usage stats.
mSystemServiceManager.startService(UsageStatsService.class);
mActivityManagerService.setUsageStatsManager(
LocalServices.getService(UsageStatsManagerInternal.class));

// Update after UsageStatsService is available, needed before performBootDexOpt.
mPackageManagerService.getUsageStatsIfNoPackageUsageInfo();
// Tracks whether the updatable WebView is in a ready state and watches for update installs.
mSystemServiceManager.startService(WebViewUpdateService.class);
}

2.3.3 startOtherServices();

//其他服务,一般添加服务都在这里添加{所有其他的java系统服务都在这里启动}

Java
private void startOtherServices() {
final Context context = mSystemContext;
AccountManagerService accountManager = null;
...
AudioService audioService = null;
MmsServiceBroker mmsService = null;
...
try {
Slog.i(TAG, "Reading configuration...");
SystemConfig.getInstance();
Slog.i(TAG, "Scheduling Policy");
ServiceManager.addService("scheduling_policy", new SchedulingPolicyService());
mSystemServiceManager.startService(TelecomLoaderService.class);
...
try {
wm.displayReady();
} catch (Throwable e) {
reportWtf("making display ready", e);
}
...
mActivityManagerService.systemReady(new Runnable() {
@Override
public void run() {
Slog.i(TAG, "Making services ready");
mSystemServiceManager.startBootPhase(
SystemService.PHASE_ACTIVITY_MANAGER_READY);
...
try {
mActivityManagerService.startObservingNativeCrashes();
} catch (Throwable e) {
reportWtf("observing native crashes", e);
}
...
}
});
}

2.4 总结
在这个run方法中,主要完成三件事情:

创建system context和system service manager

启动一些系统服务

进入主线程消息循环。

2.5 SS整体总结

SCSS
 Zygote调用startSystemServer创建system_server进程
SS调用handleSystemServerProcess完成自己的使命
handleSystemServerProcess抛出异常,最终调用com.android.server.SystemServer的main函数
main加载libandroid_server.so并调用native_init方法
在后面的3个关键方法中,启动一些系统服务
startBootstrapServices();
startCoreServices();
startOtherServices();
进入消息循环,等待请求

说明:启动系统各项服务,Java世界的核心Service都在这里启动,所以它非常重要。

相关推荐

一日一技:用Python程序将十进制转换为二进制

用Python程序将十进制转换为二进制通过将数字连续除以2并以相反顺序打印其余部分,将十进制数转换为二进制。在下面的程序中,我们将学习使用递归函数将十进制数转换为二进制数,代码如下:...

十进制转化成二进制你会吗?#数学思维

六年级奥赛起跑线:抽屉原理揭秘。同学们好,我是你们的奥耀老师。今天一起来学习奥赛起跑线第三讲二进制计数法。例一:把十进制五十三化成二进制数是多少?首先十进制就是满十进一,二进制就是满二进一。二进制每个...

二进制、十进制、八进制和十六进制,它们之间是如何转换的?

在学习进制时总会遇到多种进制转换的时候,学会它们之间的转换方法也是必须的,这里分享一下几种进制之间转换的方法,也分享两个好用的转换工具,使用它们能够大幅度的提升你的办公和学习效率,感兴趣的小伙伴记得点...

c语言-2进制转10进制_c语言 二进制转十进制

#include<stdio.h>intmain(){charch;inta=0;...

二进制、八进制、十进制和十六进制数制转换

一、数制1、什么是数制数制是计数进位的简称。也就是由低位向高位进位计数的方法。2、常用数制计算机中常用的数制有二进制、八进制、十进制和十六进制。...

二进制、十进制、八进制、十六进制间的相互转换函数

二进制、十进制、八进制、十六进制间的相互转换函数1、输入任意一个十进制的整数,将其分别转换为二进制、八进制、十六进制。2、程序代码如下:#include<iostream>usingna...

二进制、八进制、十进制和十六进制等常用数制及其相互转换

从大学开始系统的接触计算机专业,到现在已经过去十几年了,今天整理一下基础的进制转换,希望给还在上高中的表妹一个入门的引导,早日熟悉这个行业。一、二进制、八进制、十进制和十六进制是如何定义的?二进制是B...

二进制如何转换成十进制?_二进制如何转换成十进制例子图解

随着社会的发展,电器维修由继电器时代逐渐被PLC,变频器,触摸屏等工控时代所替代,特别是plc编程,其数据逻辑往往涉及到数制二进制,那么二进制到底是什么呢?它和十进制又有什么区别和联系呢?下面和朋友们...

二进制与十进制的相互转换_二进制和十进制之间转换

很多同学在刚开始接触计算机语言的时候,都会了解计算机的世界里面大多都是二进制来表达现实世界的任何事物的。当然现实世界的事务有很多很多,就拿最简单的数字,我们经常看到的数字大多都是十进制的形式,例如:我...

十进制如何转换为二进制,二进制如何转换为十进制

用十进制除以2,除的断的,商用0表示;除不断的,商用1表示余0时结束假如十进制用X表示,用十进制除以2,即x/2除以2后为整数的(除的断的),商用0表示;除以2除不断的,商用1表示除完后的商0或1...

十进制数如何转换为二进制数_十进制数如何转换为二进制数举例说明

我们经常听到十进制数和二进制数,电脑中也经常使用二进制数来进行计算,但是很多人却不清楚十进制数和二进制数是怎样进行转换的,下面就来看看,十进制数转换为二进制数的方法。正整数转二进制...

二进制转化为十进制,你会做吗?一起来试试吧

今天孩子问把二进制表示的110101改写成十进制数怎么做呀?,“二进制”简单来说就是“满二进一”,只用0和1共两个数字表示,同理我们平常接触到的“十进制”是“满十进一”,只用0-9共十个数字表示。如果...

Mac终于能正常打游戏了!苹果正逐渐淘汰Rosetta转译

Mac玩家苦转译久矣!WWDC2025苹果正式宣判Rosetta死刑,原生游戏时代终于杀到。Metal4光追和AI插帧技术直接掀桌,连Steam都连夜扛着ARM架构投诚了。看到《赛博朋克2077》...

怎么把视频的声音提出来转为音频?音频提取,11款工具实测搞定

想把视频里的声音单独保存为音频文件(MP3/AAC/WAV/FLAC)用于配音、播客、听课或二次剪辑?本文挑出10款常用工具,给出实测可复现的操作步骤、优缺点和场景推荐。1)转换猫mp3转换器(操作门...

6个mp4格式转换器测评:转换速度与质量并存!

MP4视频格式具有兼容性强、视频画质高清、文件体积较小、支持多种编码等特点,适用于网络媒体传播。如果大家想要将非MP4格式的视频转换成MP4的视频格式的话,可以使用MP4格式转换器更换格式。本文分别从...