Android 进阶——系统启动之核心SystemServer进程启动详解
Posted CrazyMo_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 进阶——系统启动之核心SystemServer进程启动详解相关的知识,希望对你有一定的参考价值。
引言
对了如果我的文章对你有些许帮助,或许你可以花几秒钟动动手指投个票,感激,直通车五星好评,加油共勉!
前面系列文章介绍了android系统的第一个用户进程——init进程由解析init.rc脚本启动,完成属性系统的初始化等工作后紧接着启动Android系统上的造物者——Zygote进程,在Zygote 进程启动过程中会把Android 最核心进程SystemServer进程创建并启动。
基于Android 26,方法在本系列文章代表Java层,函数指Native层的,仅供参考。
以后更多精选系列文章以高度完整的系列形式发布在公众号,真正的形成一套完整的技术栈,欢迎关注,目前第一个系列是关于Android系统启动系列的文章,大概有二十几篇干货:
- Android 进阶——系统启动之BootLoader 简介及内核启动(一)
- Android 进阶——系统启动之Linux init进程的创建和启动(二)
- Android 进阶——系统启动之Android init进程的创建和启动(三)
- Android 进阶——系统启动之Android init.rc脚本解析(四)
- Android 进阶——系统启动之Android init进程解析init.rc脚本(五)
- Android 进阶——系统启动之Android进程造物者Zygote 进程启动详解(六)
- Android 进阶——系统启动之核心SystemServer进程启动详解(七)
一、SystemServer 进程概述
SystemServer进程(System进程,名为system_server
)在Android 系统中运行着各种系统核心服务ActivityManagerService、PackageManagerService、ContentService、WindowManagerService等六十多种服务,为了保护Android系统,Android 应用没有权限直接访问设备的底层资源,都是通过Binder去调用SystemService中的服务代理对象。在Zygote 进程启动后,由Zygote fork自身创建SystemServer进程并马上启动执行SystemServer类的main方法。
由于System进程是由Zygote fork自身而得到的,就是说System进程复制了Zygote进程的地址空间,也同样在启动时创建了一个socket。
二、SystemServer进程的创建
整体上可以把SystemServer进程创建分为两个阶段:首先是Zygote 进程fork 创建初始化SystemServer进程,然后是返回到SystemServer进程中执行SystemServer#main方法初始化和启动各种系统服务。
/frameworks/base/cmds/app_process/app_main.cpp # main 解析init.rc 脚本传入的参数,触发AppRuntime #start函数进而执行ZygoteInit#main 方法。
1、ZygoteInit.main方法里调用startSystemServer方法触发SystemServer 进程的创建
前面分析得知在init.rc脚本中定义的Zygote进程的启动参数中包括了--start-system-server
等,因此Zygote 进程会在ZygoteInit.main方法里调用startSystemServer方法来 fork 出SystemServer进程,startSystemServer 方法主要是做了三件事:
- 为SystemServer 准备启动参数(包括制定uid和gid为1000,执行Java类为com.android.SystemServer等)
- 通过调用Zygote.forkSystemServer方法真正fork 出SystemServer进程(JNI调用nativeForkSystemServer函数)
- fork 创建SystemServer进程后,返回到SystemServer进程中,真正开始初始化SystemServer(执行
ZygoteInit.java #handleSystemServerProcess(parsedArgs)
方法)。
private static boolean startSystemServer(String abiList, String socketName)
throws MethodAndArgsCaller, RuntimeException
/* Hardcoded command line to start the system server */
//System进程启动的参数,可以看到System进程的用户ID和用户组ID都是1000,同时还有其他用户组的权限
String args[] =
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"com.android.server.SystemServer",
;
ZygoteConnection.Arguments parsedArgs = null;
int pid;
try
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
/* Request to fork the system server process */
//fork 创建System进程
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
/* For child process fork 后返回到SystemServer进程*/
if (pid == 0)
if (hasSecondZygote(abiList))
if(isBox)
waitForSecondaryZygote(socketName);
Log.d(TAG,"--------call waitForSecondaryZygote,skip this---,abiList= "+abiList);
// 处理System进程启动事宜
handleSystemServerProcess(parsedArgs);
return true;
2、Zygote.forkSystemServer 方法触发fork 创建SystemServer进程
应用启动时会调用Zygote 类的forkAndSpecialize 方法来fork出子进程,而SystemServer进程是由forkSystemServer方法 fork出来的,虽然本质都是通过JNI 调用\\frameworks\\base\\core\\jni\\com_android_internal_os_Zygote.cpp中native函数完成
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_DEFAULT, NULL, NULL, true, NULL,
NULL, NULL);
if (pid > 0)
ALOGI("System server process %d has been created", pid);
gSystemServerPid = pid;
int status;
//Zygote进程中检查SystemServer 是否启动成功
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!");
return pid;
当native层执行完毕ForkAndSpecializeCommon函数后,还会返回Zygote进程中检查SystemServer 是否启动成功,如果SystemServer 启动不成功,系统会从Zygote开始再启动一遍。
static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
jint debug_flags, jobjectArray javaRlimits,
jlong permittedCapabilities, jlong effectiveCapabilities,jint mount_external,jstring java_se_info, jstring java_se_name,bool is_system_server, jintArray fdsToClose,jstring instructionSet, jstring dataDir)
SetSigChldHandler();
...
pid_t pid = fork();
...
if (pid == 0)
rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
...
if (se_info_c_str == NULL && is_system_server)
se_name_c_str = "system_server";
if (se_info_c_str != NULL)
SetThreadName(se_name_c_str);
UnsetSigChldHandler();
env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags,
is_system_server, instructionSet);
...
return pid;
从代码中可以看到在fork之前,首先注册了SIGCHILD信号的处理函数SIGChildHandler 函数,当捕捉到这个SIGCHILD信号(通常是子进程死亡时)后,除了调用waitpid来防止子进程变“僵尸”外,还会再判断是否是SystemServer进程,如果是,Zygote进程会自杀,进而导致Init进程杀死所有用户进程并重启Zygote。
三、SystemServer 进程的初始化
1、返回ZygoteInit#handleSystemServerProcess方法SystemServer开始初始化工作
\\frameworks\\base\\core\\java\\com\\android\\internal\\os\\ZygoteInit.java
当Zygote进程在main方法里fork出SystemServer进程后,回到ZygoteInit.main方法中继续往下执行ZygoteInit#handleSystemServerProcess方法开始初始化SystemServer进程,首先将SystemServer进程的umask设为0077,这样当SystemServer 创建的文件的属性就是0077,即只有SystemServer 进程才可以访问,然后把SystemServer进程的名称修改为system_server
。
/**
* Finish remaining work for the newly forked system server process.
*/
private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller
// 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);
...
final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
if (systemServerClasspath != null)
performSystemServerDexOpt(systemServerClasspath);
if (parsedArgs.invokeWith != null)
...
else
ClassLoader cl = null;
if (systemServerClasspath != null)
cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
Thread.currentThread().setContextClassLoader(cl);
/*
* Pass the remaining arguments to SystemServer.
*/
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
首次执行时parsedArgs.invokeWith 为null,所以首先是执行 ZygoteInit.zygoteInit方法来反射调用SystemServer类的main方法。
2、执行/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java # zygoteInit 方法继续初始化System进程
在返回到System进程后最终执行 RuntimeInit.java # zygoteInit 方法继续启动System进程:
-
commonInit 方法配置System进程的时区、键盘布局等通用信息
-
nativeZygoteInit 方法在System进程中开启一个Binder线程池
-
执行invokeStaticMain方法,表示要触发类名为“"com.android.server.SystemServer”静态成员main方法,即作为System进程的”入口“
在ZygoteInit.java # startSystemServer 中fork System 进程时传递的类名为"com.android.server.SystemServer“
/**
* The main function called when started through the zygote process. This
* could be unified with main(), if the native code in nativeFinishInit()
* were rationalized with Zygote startup.<p>
* @param targetSdkVersion target SDK version
* @param argv arg strings argv 最后一个参数的值为"com.android.server.SystemServer"
*/
public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
redirectLogStreams();
commonInit();
nativeZygoteInit();
//invokeStaticMain 在这里被执行
applicationInit(targetSdkVersion, argv, classLoader);
实际上System进程进入到com.android.server.SystemServer # main方法时,已经执行了很多代码量,从严格意义上讲main方法并不是System进程的入口方法,只不过Runtime#invokeStaticMain 使用了巧妙地方法来调用它使之变成是System进程的入口。
3、执行 /frameworks/base/services/java/com/android/server/SystemServer.java # main方法完成SystemServer的初始化
在SystemServer.java # main方法里完成系统属性的初始化、核心系统服务的启动、Handler 消息机制的初始化以及其他重要系统服务的启动。
/**
* The main entry point from zygote.
*/
public static void main(String[] args)
new SystemServer().run();
private void run()
try
if (!SystemProperties.get("persist.sys.language").isEmpty())
final String languageTag = Locale.getDefault().toLanguageTag();
SystemProperties.set("persist.sys.locale", languageTag);
SystemProperties.set("persist.sys.language", "");
SystemProperties.set("persist.sys.country", "");
SystemProperties.set("persist.sys.localevar", "");
...
// Here we go!
Slog.i(TAG, "Entered the Android system server!");
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis());
//设置当前的虚拟机的运行库路径
SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
// Mmmmmm... more memory!
VMRuntime.getRuntime().clearGrowthLimit();
// The system server has to run all of the time, so it needs to be
// as efficient as possible with its memory usage.
VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
// Increase the number of binder threads in system_server
BinderInternal.setMaxThreads(sMaxBinderThreads);
// Prepare the main looper thread (this thread).
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_FOREGROUND);
android.os.Process.setCanSelfBackground(false);
Looper.prepareMainLooper();
// Initialize native services.
System.loadLibrary("android_servers");
// Check whether we failed to shut down last time we tried.
// This call may not return.
performPendingShutdown();
// Initialize the system context.
createSystemContext();
// Create the system service manager.
mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
finally
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
// Start services.
try
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
startBootstrapServices();
startCoreServices();
startOtherServices();
catch (Throwable ex)
throw ex;
finally
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
3.1、 System.loadLibrary(“android_servers”) 加载framework/base/services/jni下的libandroid_servers.so库并初始化相关native服务
3.2、 createSystemContext() 获取系统的Context并设置主题
通过ActivityThread的systemMain方法来获取ActivityThread对象进而获取系统的Context,最终设置系统主题
private void createSystemContext()
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
final Context systemUiContext = activityThread.getSystemUiContext();
systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
3.2.1、在ActivityThread.systemMain方法中创建ActivityThread对象并调用ActivityThread#attach方法
public static ActivityThread systemMain()
...
ActivityThread thread = new ActivityThread();
thread.attach(true);
return thread;
3.2.2、在ActivityThread.attach方法中创建Instrumentation对象和Context(ContextImpl)对象
private void attach(boolean system)
sCurrentActivityThread = this;
mSystemThread = system;
if (!system)
...
else
try
mInstrumentation = new Instrumentation();
ContextImpl context = ContextImpl.createAppContext(this, getSystemContext().mPackageInfo);
mInitialApplication = context.mPackageInfo.makeApplication(true, null);
mInitialApplication.onCreate();
catch (Exception e)
throw new RuntimeException(
"Unable to instantiate Application():" + e.toString(), e);
...
ViewRootImpl.addConfigCallback(configChangedCallback);
attach时传入的system参数值为true时,会创建一个类似应用的环境,创建了ContextImpl、Application对象并调用Application#onCreate方法,完全是在创建一个应用。每一个上下文对象都需要对应一个APK文件
,注意查看ContextImpl里的PackgeInfo对象(来源于ActivityThread#getSystemContext方法)
每一个上下文对象都需要对应一个APK文件
,换言之每一个Context对象对应着一个APP的环境,同时每个App 也对应着一个Application对象
public ContextImpl getSystemContext()
synchronized (this)
if (mSystemContext == null)
mSystemContext = ContextImpl.createSystemContext(this);
return mSystemContext;
当mSystemContext为null时,会调用ContextImpl.createSystemContext方法中创建。
3.2.3、在ContextImpl.createSystemContext方法中创建LoadedApk对象
static ContextImpl createSystemContext(ActivityThread mainThread)
LoadedApk packageInfo = new LoadedApk(mainThread);
ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
null);
context.setResources(packageInfo.getResources());
context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
context.mResourcesManager.getDisplayMetrics());
return context;
而LoadedApk 构造方法
/**
* Create information about the system package.
* Must call @link #installSystemApplicationInfo later.
*/
LoadedApk(ActivityThread activityThread)
mActivityThread = activityThread;
mApplicationInfo = new ApplicationInfo();
mApplicationInfo.packageName = "android";
mPackageName = "android";
...
mClassLoader = ClassLoader.getSystemClassLoader();
mResources = Resources.getSystem();
可以看到包名为android
(framework-res.apk的包名也是android),自然getSystemContext方法放回的mSystemContext 所对应的apk文件其实是framework-res.apk,当attach方法被执行时,新建的ContextImpl对象本质上是在复制mSystemContext,最终创建的Application对象相当于是framework-res.apk。总而言之,Activity#systemMain方法相当于创建了一个framework-res.apk 的上下文环境。
3.3、创建SystemServiceManager对象(管理系统服务)
3.4、startBootstrapServices、startCoreServices、startOtherServices启动所有系统服务
至于具体系统服务的启动系列留到后续文章一一详细分析,需要注意的是除了初始化系统服务之外,SystemServer还需要监控各种系统服务是否正常工作,因此设计了一套软件“看门狗方案”并在startOtherServices方法里创建并启动,至此SystemServer进程启动完毕,SystemServer进程在初始化的时候也需要和普通应用进程一样,创建一个类似应用的环境。
以上是关于Android 进阶——系统启动之核心SystemServer进程启动详解的主要内容,如果未能解决你的问题,请参考以下文章
Android 进阶——系统启动之Framework 核心ActivitityManagerService服务启动
Android 进阶——系统启动之Framework 核心ActivitityManagerService服务启动
Android 进阶——系统启动之Framework 核心ActivitityManagerService服务启动
Android 进阶——系统启动之核心SystemServer进程启动详解