系統(tǒng)中的大管家—SystemServer進程
本文轉載自微信公眾號「碼上積木」,可以通過以下二維碼關注。轉載本文請聯(lián)系碼上積木公眾號。
前言
上篇說到Android系統(tǒng)的啟動流程,Zygote進程fork的第一個進程就是SystemServer進程。
這個進程負責啟動和管理JavaFramework層,也就是提供了框架層的很多服務,比如我們熟知的AMS,PMS,WMS,還有DisplayManagerService、CameraService等等,也就是說它掌握了Android系統(tǒng)中的命脈,是Android系統(tǒng)中的大管家。
一起瞅瞅吧~
(本文源碼基于Android9.0)
誕生
之前在Android系統(tǒng)的啟動過程中???說到,SystemServer進程是由Zygote進程fork而來。
fork()函數通過系統(tǒng)調用創(chuàng)建一個與原來進程幾乎完全相同的進程,可以理解為COPY了一個進程出來,而這個新進程就是它的子進程。
而關于SystemServer的誕生,還要從ZygoteInit的forkSystemServer方法說起...(只保留主要代碼)
- private static Runnable forkSystemServer(String abiList, String socketName,
- ZygoteServer zygoteServer) {
- //...
- // 1
- int pid;
- pid = Zygote.forkSystemServer(
- parsedArgs.uid, parsedArgs.gid,
- parsedArgs.gids,
- parsedArgs.runtimeFlags,
- null,
- parsedArgs.permittedCapabilities,
- parsedArgs.effectiveCapabilities);
- /* For child process */
- if (pid == 0) {
- //2
- zygoteServer.closeServerSocket();
- //3
- return handleSystemServerProcess(parsedArgs);
- }
- return true;
- }
- /**
- * Finish remaining work for the newly forked system server process.
- */
- private static Runnable handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs) {
- //...
- /*
- * Pass the remaining arguments to SystemServer.
- */
- ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
- }
- public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
- //...
- //4
- RuntimeInit.commonInit();
- //5
- ZygoteInit.nativeZygoteInit();
- //6
- return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
- }
startSystemServer方法中:
- 1、調用forkSystemServer方法創(chuàng)建了子進程——SystemServer進程。
- 2、fork之后,這里判斷了fork的返回值pid是否等于0,如果等于0,就代表fork成功,就處在SystemServer進程中了。然后關閉了從Zygote進程fork帶來的Socket對象。
- 3、然后調用了handleSystemServerProcess方法,并最終走到zygoteInit,做了一些新進程的初始化工作。
zygoteInit方法中:
- 4、commonInit方法就是做了一些進程通用的初始化工作,比如設置時區(qū),重置log配置。
- 5、nativeZygoteInit方法通過JNI會走到native層,主要的工作就是創(chuàng)建了新的Binder線程池,這樣SystemServer才能和各大app進程進行通信。
- 6、applicationInit方法,最終會走到findStaticMain方法中,通過反射調用SystemServer類的main方法,簡單貼下代碼:
- protected static Runnable findStaticMain(String className, String[] argv,
- ClassLoader classLoader) {
- Class<?> cl;
- try {
- cl = Class.forName(className, true, classLoader);
- }
- //...
- Method m;
- try {
- m = cl.getMethod("main", new Class[] { String[].class });
- }
- //...
- return new MethodAndArgsCaller(m, argv);
- }
工作
SystemServer進程創(chuàng)建出來了,并且做了一些初始化工作,接下來就來到了main方法了,顧名思義,肯定要開始正經主要的工作了。
- public static void main(String[] args) {
- new SystemServer().run();
- }
- private void run() {
- try {
- //...
- // 1
- 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);
- // 2
- System.loadLibrary("android_servers");
- // 3
- performPendingShutdown();
- // 4
- createSystemContext();
- // 5
- mSystemServiceManager = new SystemServiceManager(mSystemContext);
- mSystemServiceManager.setStartInfo(mRuntimeRestart,
- mRuntimeStartElapsedTime, mRuntimeStartUptime);
- LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
- // Prepare the thread pool for init tasks that can be parallelized
- SystemServerInitThreadPool.get();
- } finally {
- traceEnd();
- }
- //...
- // Start services.
- try {
- //6
- startBootstrapServices();
- //7
- startCoreServices();
- //8
- startOtherServices();
- SystemServerInitThreadPool.shutdown();
- }
- //...
- // Loop forever.
- Looper.loop();
- throw new RuntimeException("Main thread loop unexpectedly exited");
- }
- 1、準備主線程,Looper。
- 2、加載動態(tài)庫。
- 3、檢測上次關機過程是否失敗。
- 4、初始化系統(tǒng)上下文。
- 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);
- }
在這個方法中,創(chuàng)建了ActivityThread類,獲取了上下文,并設置了一些系統(tǒng)主題。
- 5、創(chuàng)建SystemServiceManager,用于后續(xù)的系統(tǒng)服務管理創(chuàng)建等工作。
run方法最后的工作就是啟動三個服務類型的服務,也是我們重點關注的,分別是引導服務,核心服務,其他服務。
這些服務一共有100多個,關系著Android整個應用生態(tài),下面我們具體說下。
- 6、啟動引導服務
- private void startBootstrapServices() {
- //安裝APK服務
- traceBeginAndSlog("StartInstaller");
- Installer installer = mSystemServiceManager.startService(Installer.class);
- traceEnd();
- //AMS,負責四大組件的啟動調度等工作
- mActivityManagerService = mSystemServiceManager.startService(
- ActivityManagerService.Lifecycle.class).getService();
- mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
- mActivityManagerService.setInstaller(installer);
- traceEnd();
- // 管理和顯示背光LED等服務
- traceBeginAndSlog("StartLightsService");
- mSystemServiceManager.startService(LightsService.class);
- traceEnd();
- //PMS,負責APK安裝,解析卸載等工作
- traceBeginAndSlog("StartPackageManagerService");
- mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
- mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
- mFirstBoot = mPackageManagerService.isFirstBoot();
- mPackageManager = mSystemContext.getPackageManager();
- traceEnd();
- //...
- }
引導服務中,有幾個我們畢竟熟悉的,比如AMS、PMS。
- 7、啟動核心服務
- private void startCoreServices() {
- traceBeginAndSlog("StartBatteryService");
- // 管理電池相關服務
- mSystemServiceManager.startService(BatteryService.class);
- traceEnd();
- // 收集用戶使用時長服務
- traceBeginAndSlog("StartUsageService");
- mSystemServiceManager.startService(UsageStatsService.class);
- mActivityManagerService.setUsageStatsManager(
- LocalServices.getService(UsageStatsManagerInternal.class));
- traceEnd();
- // Webview更新服務
- if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_WEBVIEW)) {
- traceBeginAndSlog("StartWebViewUpdateService");
- mWebViewUpdateService = mSystemServiceManager.startService(WebViewUpdateService.class);
- traceEnd();
- }
- //...
- }
- 8、啟動其他服務
- private void startOtherServices() {
- //...
- //電話管理服務
- traceBeginAndSlog("StartTelephonyRegistry");
- telephonyRegistry = new TelephonyRegistry(context);
- ServiceManager.addService("telephony.registry", telephonyRegistry);
- traceEnd();
- //WMS,窗口管理服務,也是打交道比較多的
- traceBeginAndSlog("StartWindowManagerService");
- ConcurrentUtils.waitForFutureNoInterrupt(mSensorServiceStart, START_SENSOR_SERVICE);
- mSensorServiceStart = null;
- wm = WindowManagerService.main(context, inputManager,
- mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
- !mFirstBoot, mOnlyCore, new PhoneWindowManager());
- ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
- DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
- ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
- /* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
- traceEnd();
- //輸入事件管理服務
- traceBeginAndSlog("StartInputManager");
- inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
- inputManager.start();
- traceEnd();
- //...
- }
啟動了這么多服務,我們再看一下服務都是怎么具體啟動的:
- public <T extends SystemService> T startService(Class<T> serviceClass) {
- try {
- final String name = serviceClass.getName();
- // Create the service.
- final T service;
- try {
- Constructor<T> constructor = serviceClass.getConstructor(Context.class);
- service = constructor.newInstance(mContext);
- } //...
- startService(service);
- return service;
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
- }
- }
- // 所有系統(tǒng)服務的集合
- private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();
- public void startService(@NonNull final SystemService service) {
- // Register it.
- mServices.add(service);
- // Start it.
- long time = SystemClock.elapsedRealtime();
- try {
- service.onStart();
- } catch (RuntimeException ex) {
- throw new RuntimeException("Failed to start service " + service.getClass().getName()
- + ": onStart threw an exception", ex);
- }
- warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
- }
可以看到,首先通過反射創(chuàng)建了對應的Service類,然后把對應的Service加入到mServices集合中,完成注冊。然后調用onStart方法啟動對應的Service,完成初始化工作。
到這里,SystemServer的啟動工作就完成了,再來回顧下,這個過程,到底干了些啥?
- 首先,Zygote fork了SystemServer這個子進程,然后關閉了原有的socket,創(chuàng)建了新的Binder線程池。
- 其次,做了一些初始化工作,創(chuàng)建了Context對象,創(chuàng)建了SystemServiceManager類,用于管理所有的系統(tǒng)服務。
- 最后,啟動了三類系統(tǒng)服務,分別是引導服務,核心服務和其他服務。
體系知識延伸
Socket和Binder
我們注意到,在SystemServer被fork出來之后,做了一個操作就是關閉了Sokcet,啟動了Binder線程池用于進程間通信。問題來了,為啥Zygote進程是用Socket通信,而SystemServer進程是用Binder進行通信呢?
其實這是兩個問題,第一個問題是問為什么Android獲取系統(tǒng)服務是用的Binder進程通信呢?
這就涉及到Binder的知識點了,Binder之所以被設計出來,就是因為它有區(qū)別于其他IPC方式的兩大優(yōu)點:
- 性能高,效率高:傳統(tǒng)的IPC(套接字、管道、消息隊列)需要拷貝兩次內存、Binder只需要拷貝一次內存、共享內存不需要拷貝內存。
- 安全性好:接收方可以從數據包中獲取發(fā)送發(fā)的進程Id和用戶Id,方便驗證發(fā)送方的身份,其他IPC想要實驗只能夠主動存入,但是這有可能在發(fā)送的過程中被修改。
第二個問題就是,為什么Zygote進程不用Binder而用Socket通信呢?這也是wanAndroid中的一個問題:
每日一問 | Activity啟動流程中,大部分都是用Binder通訊,為啥跟Zygote通信的時候要用socket呢?(https://www.wanandroid.com/wenda/show/10482)
評論區(qū)主要有以下觀點:
- ServiceManager不能保證在zygote起來的時候已經初始化好,所以無法使用Binder。
- Socket 的所有者是 root,只有系統(tǒng)權限用戶才能讀寫,多了安全保障。
- Binder工作依賴于多線程,但是fork的時候是不允許存在多線程的,多線程情況下進程fork容易造成死鎖,所以就不用Binder了。
Binder線程池
Binder線程池到底是什么?之前有讀者也問過類似的問題。
Binder線程池位于服務端,它的主要作用就是將每個業(yè)務模塊的Binder請求統(tǒng)一轉發(fā)到遠程Servie中去執(zhí)行,從而避免了重復創(chuàng)建Service的過程。也就是服務端只有一個,但是可以處理多個不同客戶端的Binder請求。
AMS,PMS,WMS
在SystemServer進程啟動的過程中,也啟動了很多系統(tǒng)服務,其中就包括和應用交互比較多的三個服務:
- AMS,ActivityManagerService,負責四大組件的啟動,切換,調度工作。
- PMS,PackageManagerService,負責APK的安裝,解析,卸載工作。
- WMS,WindowManagerService,負責窗口啟動,添加,刪除等工作。
參考
《Android進階解密》 https://www.wanandroid.com/wenda/show/10482 https://blog.csdn.net/yiranfeng/article/details/103550262