文章目录

  • 创建 SystemServer 进程
  • SystemServer 初始化
  • 总结一下 SystemServer 启动分几步

SystemServer 是系统的核心之一,大部分android提供的服务都运行在这个进程中,SystemServer 中运行的服务大概有八十多种。为了防止应用进程对系统造成破坏,Android应用进程没有权限直接访问设备的底层资源,只能通过 SystemServer 中的服务代理访问。通过 Binder 用户进程使用 SystemServer 中的服务并没有太多不便之处。

创建 SystemServer 进程

  • 之前讲过,Init.rc 中引用了 import /init.${ro.zygote}.rc ,实际上对应zygote 服务启动参数里面包含如下内容:
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server

因此,在 ZygoteInit 的 main 方法中调用了如下代码创建 SystemServer

if (startSystemServer) {// 准备 SystemServer 参数并且 fork 出 SystemServer 进程Runnable r = forkSystemServer(abiList, socketName, zygoteServer);// {@code r == null} in the parent (zygote) process, and {@code r != null} in the// child (system_server) process.if (r != null) {r.run();return;}}
  • forkSystemServer() 代码如下:
private static Runnable forkSystemServer(String abiList, String socketName,ZygoteServer zygoteServer) {// 代码略...../* Hardcoded command line to start the system server */// 准备参数 ,可以看到 进程 ID 和 组ID 都为 1000String 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",};ZygoteConnection.Arguments parsedArgs = null;int pid;try {parsedArgs = new ZygoteConnection.Arguments(args);ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);boolean profileSystemServer = SystemProperties.getBoolean("dalvik.vm.profilesystemserver", false);if (profileSystemServer) {parsedArgs.runtimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;}/* Request to fork the system server process */pid = Zygote.forkSystemServer(parsedArgs.uid, parsedArgs.gid,parsedArgs.gids,parsedArgs.runtimeFlags,null,parsedArgs.permittedCapabilities,parsedArgs.effectiveCapabilities);} 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;}

forkSystemServer 主要做了以下几件事

  • 第一件事 准备启动参数,可以看到 uid 和 gid 都为 1000;它的可执行文件为 package com.android.server.SystemServer
  • 第二件事 调用 Zygote.forkSystemServer fork 出 SystemServer 进程。下面贴出了 Zygote.java 中 forkSystemServer 方法,其中也是调用了 nativeForkSystemServer() 方法。其对应的 native 函数在 com_android_internal_os_Zygote.cpp 文件中。
  • forkSystemServer
    public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {VM_HOOKS.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);}VM_HOOKS.postForkCommon();return pid;}
  • nativeForkSystemServer
    Zygote 会检查 SystemServer 是否启动成功,如果启动失败则会重启Zygote进程
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 permittedCapabilities,jlong effectiveCapabilities) {// fork pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,runtime_flags, rlimits,permittedCapabilities, effectiveCapabilities,MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL,NULL, false, NULL, NULL);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!");}bool low_ram_device = GetBoolProperty("ro.config.low_ram", false);bool per_app_memcg = GetBoolProperty("ro.config.per_app_memcg", low_ram_device);if (per_app_memcg) {// Assign system_server to the correct memory cgroup.// Not all devices mount /dev/memcg so check for the file first// to avoid unnecessarily printing errors and denials in the logs.if (!access("/dev/memcg/system/tasks", F_OK) &&!WriteStringToFile(StringPrintf("%d", pid), "/dev/memcg/system/tasks")) {ALOGE("couldn't write %d to /dev/memcg/system/tasks", pid);}}}return pid;
}

上面代码调用了 ForkAndSpecializeCommon() 函数来fork 进程,在这个方法中调用了 SetSignalHandlers(); 函数。
还调用了 SigChldHandler 函数处理 SIGCHLD 信号,代码如下

static void SigChldHandler(int /*signal_number*/) {//...while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {// ...if (pid == gSystemServerPid) {// 如果 SystemServer 死亡则退出 zygote ALOGE("Exit zygote because system server (%d) has terminated", pid);kill(getpid(), SIGKILL);}}// ...
}

继续回到 Zygote.Init 的 forkSystemServer函数

第三件事:fork() 出子进程后,调用了 handleSystemServerProcess() 来初始化 SystemServer

        /* For child process */if (pid == 0) {if (hasSecondZygote(abiList)) {waitForSecondaryZygote(socketName);}zygoteServer.closeServerSocket();return handleSystemServerProcess(parsedArgs);}
  • handleSystemServerProcess() 如下注释操作;最后会执行到 SystemServer 的 main() 方法
    /*** Finish remaining work for the newly forked system server process.*/private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {// set umask to 0077 so new files and directories will default to owner-only permissions.// 将 SystemServer 进程umask设置成 0077 这样只有SystemServer可以访问Os.umask(S_IRWXG | S_IRWXO);if (parsedArgs.niceName != null) {// 修改进程名为参数传入的 niceName (system_server)Process.setArgV0(parsedArgs.niceName);}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.boolean profileSystemServer = SystemProperties.getBoolean("dalvik.vm.profilesystemserver", false);if (profileSystemServer && (Build.IS_USERDEBUG || Build.IS_ENG)) {try {prepareSystemServerProfile(systemServerClasspath);} catch (Exception e) {Log.wtf(TAG, "Failed to set up system server profile", e);}}}// invokeWith 通常为 nullif (parsedArgs.invokeWith != null) {String[] args = parsedArgs.remainingArgs;// 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.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.invokeWith,parsedArgs.niceName, parsedArgs.targetSdkVersion,VMRuntime.getCurrentInstructionSet(), null, args);throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");} else {ClassLoader cl = null;if (systemServerClasspath != null) {cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);Thread.currentThread().setContextClassLoader(cl);}/** Pass the remaining arguments to SystemServer. 在这里面会执行 SystemServer 的 main 方法。*/return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);}/* should never reach here */}

SystemServer 初始化

  • SystemServer 的入口如下:new 了一个 SystemServer 并执行 run 方法
    /*** The main entry point from zygote.*/public static void main(String[] args) {new SystemServer().run();}
  • run
    主要任务:
    设置 JVM 运行库路径
    调整系统时间
    设置虚拟机堆利用率
    装载 libandroid_services.so 库
    获取 system context.设置 Context
    创建并运行所有 Java 服务
    Looper.loop() 开始消息循环
private void run() {try {traceBeginAndSlog("InitBeforeStartServices");// 如果时间不正确调整系统时间if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {Slog.w(TAG, "System clock is before 1970; setting to 1970.");SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);}//// Default the timezone property to GMT if not set.// 默认 GMT 的时区 //String timezoneProperty =  SystemProperties.get("persist.sys.timezone");if (timezoneProperty == null || timezoneProperty.isEmpty()) {Slog.w(TAG, "Timezone not set; setting to GMT.");SystemProperties.set("persist.sys.timezone", "GMT");}// 设置语言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", "");}// The system server should never make non-oneway callsBinder.setWarnOnBlocking(true);// The system server should always load safe labelsPackageItemInfo.setForceSafeLabels(true);// Default to FULL within the system server.SQLiteGlobal.sDefaultSyncMode = SQLiteGlobal.SYNC_MODE_FULL;// Deactivate SQLiteCompatibilityWalFlags until settings provider is initializedSQLiteCompatibilityWalFlags.init(null);// Here we go!Slog.i(TAG, "Entered the Android system server!");int uptimeMillis = (int) SystemClock.elapsedRealtime();EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis);if (!mRuntimeRestart) {MetricsLogger.histogram(null, "boot_system_server_init", uptimeMillis);}// In case the runtime switched since last boot (such as when// the old runtime was removed in an OTA), set the system// property so that it is in sync. We can | xq oqi't do this in// libnativehelper's JniInvocation::Init code where we already// had to fallback to a different runtime because it is// running as root and we need to be the system user to set// the property. http://b/11463182// 下面设置一些虚拟机参数 运行路径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);// Some devices rely on runtime fingerprint generation, so make sure// we've defined it before booting further.Build.ensureFingerprintProperty();// Within the system server, it is an error to access Environment paths without// explicitly specifying a user.Environment.setUserRequired(true);// Within the system server, any incoming Bundles should be defused// to avoid throwing BadParcelableException.BaseBundle.setShouldDefuse(true);// Within the system server, when parceling exceptions, include the stack traceParcel.setStackTraceParceling(true);// Ensure binder calls into the system always run at foreground priority.BinderInternal.disableBackgroundScheduling(true);// Increase the number of binder threads in system_serverBinderInternal.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();Looper.getMainLooper().setSlowLogThresholdMs(SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);// Initialize native services. 装载 libandroid_servers.so 库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. 创建 SystemServiceManagermSystemServiceManager = new SystemServiceManager(mSystemContext);mSystemServiceManager.setStartInfo(mRuntimeRestart,mRuntimeStartElapsedTime, mRuntimeStartUptime);LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);// Prepare the thread pool for init tasks that can be parallelizedSystemServerInitThreadPool.get();} finally {traceEnd();  // InitBeforeStartServices}// Start services. 启动所有的 Java service try {traceBeginAndSlog("StartServices");startBootstrapServices();startCoreServices();startOtherServices();SystemServerInitThreadPool.shutdown();} catch (Throwable ex) {Slog.e("System", "******************************************");Slog.e("System", "************ Failure starting system services", ex);throw ex;} finally {traceEnd();}StrictMode.initVmDefaults(null);if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {int uptimeMillis = (int) SystemClock.elapsedRealtime();MetricsLogger.histogram(null, "boot_system_server_ready", uptimeMillis);final int MAX_UPTIME_MILLIS = 60 * 1000;if (uptimeMillis > MAX_UPTIME_MILLIS) {Slog.wtf(SYSTEM_SERVER_TIMING_TAG,"SystemServer init took too long. uptimeMillis=" + uptimeMillis);}}// Loop forever.Looper.loop();throw new RuntimeException("Main thread loop unexpectedly exited");}
  • createSystemContext() ; 调用了 ActivityThread的静态方法 systemMain();得到了 ActivityThread对象,然后通过activityThread.getSystemContext 获取 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);}
  • ActivityThread.systemMain();
    从下面代码中可以看出,在 systemMain中创建了 ActivityThread 对象。然后使用 true 调用了 thread.attach(true, 0);
    public static ActivityThread systemMain() {// The system process on low-memory devices do not get to use hardware// accelerated drawing, since this can add too much overhead to the// process.if (!ActivityManager.isHighEndGfx()) {ThreadedRenderer.disable(true);} else {ThreadedRenderer.enableForegroundTrimming();}ActivityThread thread = new ActivityThread();thread.attach(true, 0);return thread;}
  • 为什么 SystemServer 需要创建 ActivityThread 呢?

Zygote启动应用后将执行 main 方法,这里实际上 SystemServer 不仅是一个后台进程,它也是运行着组件 Service 的进程。很多系统对话框都是从 SystemServer 弹出的。因此 SystemServer 也需要上下文环境,attach方法传入 true 代表 SystemServer 中调用的。主要代码代码如下:

// 如果传入 true 走下面代码 这里就像创建普通应用一样 创建了ContextImpl 还执行了 application 的 onCreate 方法
android.ddm.DdmHandleAppName.setAppName("system_process",UserHandle.myUserId());try {                mInstrumentation = new Instrumentation();mInstrumentation.basicInit(this);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);}

那么 SystemServer 对应 的 apk 是哪个呢?

ContextImpl context = ContextImpl.createAppContext(this, getSystemContext().mPackageInfo);

上面这行代码 getSystemContext() 在 mContetxt为null的情况 调用了 ContextImpl.createSystemContext

    public ContextImpl getSystemContext() {synchronized (this) {if (mSystemContext == null) {mSystemContext = ContextImpl.createSystemContext(this);}return mSystemContext;}}
  • ContextImpl.createSystemContext
    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 用来保存一个 apk 信息,这个构造方法传入为使用 “android” 为包名而 framework_res.apk 的包名为 android 。所以启动的为 framework_res.apk。再回述前面 attach 创建的 ContextImpl 实际上是复制 mSystemContext 对象,创建的 application 为 framework_res.apk。所以 systemMain 创建了 framework_res.apk 的上下文环境。

总结一下 SystemServer 启动分几步

  • 启动 binder 机制
  • 启动各类系统服务
  • 进入 Loop 循环

Android SystemServer 进程相关推荐

  1. Android 10.0 系统启动之SystemServer进程-[Android取经之路]

    摘要:上一节讲解了Zygote进程的整个启动流程.Zygote是所有应用的鼻祖.SystemServer和其他所有Dalivik虚拟机进程都是由Zygote fork而来.Zygote fork的第一 ...

  2. android:process=.server,Android启动(三)----开启SystemServer进程

    前面已经讲到,从C/C++层进入了Java层,即调用了ZygoteInit.main()函数,那么接下来会发生什么事情呢? 源码参考Android4.1.1,涉及的文件有ZygoteInit.java ...

  3. 从源码角度看Android系统SystemServer进程启动过程

    SystemServer进程是由Zygote进程fork生成,进程名为system_server,主要用于创建系统服务. 备注:本文将结合Android8.0的源码看SystemServer进程的启动 ...

  4. Android 系统(246)---SystemServer进程的启动流程

    Android进程系列第四篇---SystemServer进程的启动流程 一.内容预览 内容预览.png 二.概述 前面进程系列已经更新了三篇,本文(基于Android O源码),第三篇中System ...

  5. Android系统(245)---SystemServer进程的创建流程

    Android进程系列第三篇---SystemServer进程的创建流程 一.内容预览 SystemServer进程的启动.png 二.概述 前面进程系列已经更新了两篇,本文(基于Android O源 ...

  6. Android 系统(14)---SystemServer进程启动过程

    SystemServer进程的启动 在上一篇文章Framework学习(二)Zygote进程启动过程中,我们已经知道Zygote进程会启动SystemServer进程,但具体启动流程还没有涉及,本文我 ...

  7. android system_server中的dump_Android 10.0系统启动之SystemServer进程(二)

    感谢您的阅读与点赞!欢迎点击右上角关注:「大猫玩程序」 微信公众号:大猫玩程序 上一节讲解了SystemServer的架构以及被Zygote 进程fork的流程,这一节重点讲解SystemServer ...

  8. android framework-zygote进程

    Zygote进程:可以看到zygote的父进程是init进程 一.Zygote整体时序图 涉及源码路径 android-10.0.0_r41\frameworks\base\cmds\app_proc ...

  9. android重要进程的主要功能

    使用adb命令 adb shell ps -p 或者 adb shell ps -p -t -P 可以发现很多进程信息, 那么问题来了. 这些进程的主要功能是什么? 命令执行结果如下: USER   ...

  10. Android Framework- Zygote进程以及其初始化

    文章目录 Zygote 概述 Zygote 进程的初始化 app_process 的 main 函数 main函数启动流程 启动虚拟机 AndroidRuntime类 启动虚拟机 初始化工作 Zygo ...

最新文章

  1. 有格调的读书人,朋友圈是什么样的?
  2. python3 字典修改键(key)的方法
  3. 【Android 异步操作】线程池 ( 线程池作用 | 线程池种类 | 线程池工作机制 | 线程池任务调度源码解析 )
  4. pyhanlp 分词与词性标注
  5. ZYAR20A 亚克力2驱 蓝牙 298寻迹避障机器人 —— 接线过程
  6. [转:作者: 出处:javaresearch ]选择JSF不选Struts的十大理由
  7. 小猿圈Linux 之用户和用户组管理(二)
  8. gpedit msc组策略面板 win10在哪里_Win10家庭版找不到组策略gpedit.msc的解决方法
  9. 【Java 编程】文件操作,文件内容的读写—数据流
  10. layer 一张表按钮根据一个id 查询相关信息
  11. 15.凤凰架构:构建可靠的大型分布式系统 --- 服务网格
  12. Set和Map的区别 (@es6)
  13. java服务写在哪里_【Java学习笔记】如何写一个简单的Web Service
  14. 【ATSC】韩国:2017年将迎来ATSC3.0广播时代
  15. 手机图形计算器matlab,Mathlab计算器安卓版
  16. 字符设备驱动应用---LED设备驱动实现
  17. 《如何阅读一本书》读书计划
  18. [每日一氵] linux 批量删除某个名字的文件夹
  19. 酷Q自动升级失败的可能解决方法
  20. 工作学习中word及电脑常备小知识(C盘清理、电脑上微信记录清理)

热门文章

  1. c51单片机时钟程序汇编语言,51单片机时钟汇编程序
  2. SCU4487 king's trouble I(深搜DFS)
  3. C语言 逻辑运算符及其优先次序(一)
  4. json表示map_简单json 转换为 map、对象
  5. Python3.7+tkinter实现身高计算器
  6. Golang环境windows 设置 GOROOT 和 GOPATH
  7. python绘图画猫咪_Turtle库画小猫咪
  8. 微信小游戏代码包侵权的一种解决方案
  9. linux驱动面试题2018(面试题整理,含答案)
  10. excel表格的边框线怎么去除html,在EXCEL中如何去掉表头的边框线