Android系统启动流程(三)解析SyetemServer进程启动过程

上一篇我们学习了Zygote进程,并且知道Zygote进程启动了SyetemServer进程,那么这一篇我们就来学习Android7.0版本的SyetemServer进程的启动过程。" tag:

  • Android框架层
  • Android系统启动 categories:
  • Android框架层

本文首发于微信公众号「刘望舒」

前言

上一篇我们学习了Zygote进程,并且知道Zygote进程启动了SyetemServer进程,那么这一篇我们就来学习Android7.0版本的SyetemServer进程的启动过程。

<!--more-->

1.Zygote启动SyetemServer进程

在上一篇文章中我们讲到在ZygoteInit.java的startSystemServer函数中启动了SyetemServer进程,如下所示。 frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

1 private static boolean startSystemServer(String abiList, String socketName) 2 throws MethodAndArgsCaller, RuntimeException { 3 ... 4 if (pid == 0) { 5 if (hasSecondZygote(abiList)) { 6 waitForSecondaryZygote(socketName); 7 } 8 handleSystemServerProcess(parsedArgs); 9 } 10 return true; 11 }

在startSystemServer函数中调用handleSystemServerProcess来启动SyetemServer进程。

2.SyetemServer进程启动过程

handleSystemServerProcess函数的代码如下所示。

1 private static void handleSystemServerProcess( 2 ZygoteConnection.Arguments parsedArgs) 3 throws ZygoteInit.MethodAndArgsCaller { 4 closeServerSocket();//1 5 ... 6 if (parsedArgs.invokeWith != null) { 7 ... 8 } else { 9 ClassLoader cl = null; 10 if (systemServerClasspath != null) { 11 cl = createSystemServerClassLoader(systemServerClasspath, 12 parsedArgs.targetSdkVersion); 13 Thread.currentThread().setContextClassLoader(cl); 14 } 15 RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);//2 16 } 17 }

SyetemServer进程是复制了Zygote进程的地址空间,因此也会得到Zygote进程创建的Socket,这个Socket对于SyetemServer进程没有用处,因此,需要注释1处的代码来关闭该Socket。在注释2处调用RuntimeInit的zygoteInit函数,它的代码如下所示。

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

1public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) 2 throws ZygoteInit.MethodAndArgsCaller { 3 if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote"); 4 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit"); 5 redirectLogStreams(); 6 commonInit(); 7 nativeZygoteInit();//1 8 applicationInit(targetSdkVersion, argv, classLoader);//2 9 }

注释1处调用nativeZygoteInit函数,一看函数的名称就知道调用Native层的代码。

启动Binder线程池

接着我们来查看nativeZygoteInit函数对用的JNI文件,如下所示。 frameworks/base/core/jni/AndroidRuntime.cpp

1static const JNINativeMethod gMethods[] = { 2 { "nativeFinishInit", "()V", 3 (void*) com_android_internal_os_RuntimeInit_nativeFinishInit }, 4 { "nativeZygoteInit", "()V", 5 (void*) com_android_internal_os_RuntimeInit_nativeZygoteInit }, 6 { "nativeSetExitWithoutCleanup", "(Z)V", 7 (void*) com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup }, 8};

通过JNI的gMethods数组,可以看出nativeZygoteInit函数对应的是JNI文件AndroidRuntime.cpp的com_android_internal_os_RuntimeInit_nativeZygoteInit函数:

1... 2static AndroidRuntime* gCurRuntime = NULL; 3... 4static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz) 5{ 6 gCurRuntime->onZygoteInit(); 7} 8

这里gCurRuntime是AndroidRuntime类型的指针,AndroidRuntime的子类AppRuntime在app_main.cpp中定义,我们来查看AppRuntime的onZygoteInit函数,代码如下所示。 frameworks/base/cmds/app_process/app_main.cpp

1 virtual void onZygoteInit() 2 { 3 sp<ProcessState> proc = ProcessState::self(); 4 ALOGV("App process: starting thread pool.\n"); 5 proc->startThreadPool();//1 6 }

注释1处的代码用来启动一个Binder线程池,这样SyetemServer进程就可以使用Binder来与其他进程进行通信了。看到这里我们知道RuntimeInit.java的nativeZygoteInit函数主要做的就是启动Binder线程池。

invokeStaticMain

我们再回到RuntimeInit.java的代码,在注释2处调用了applicationInit函数,代码如下所示。

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

1 private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) 2 throws ZygoteInit.MethodAndArgsCaller { 3... 4 invokeStaticMain(args.startClass, args.startArgs, classLoader); 5 }

applicationInit函数中主要调用了invokeStaticMain函数:

1 private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader) 2 throws ZygoteInit.MethodAndArgsCaller { 3 Class<?> cl; 4 try { 5 cl = Class.forName(className, true, classLoader);//1 6 } catch (ClassNotFoundException ex) { 7 throw new RuntimeException( 8 "Missing class when invoking static main " + className, 9 ex); 10 } 11 Method m; 12 try { 13 m = cl.getMethod("main", new Class[] { String[].class });//2 14 } catch (NoSuchMethodException ex) { 15 throw new RuntimeException( 16 "Missing static main on " + className, ex); 17 } catch (SecurityException ex) { 18 throw new RuntimeException( 19 "Problem getting static main on " + className, ex); 20 } 21 int modifiers = m.getModifiers(); 22 if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) { 23 throw new RuntimeException( 24 "Main method is not public and static on " + className); 25 } 26 throw new ZygoteInit.MethodAndArgsCaller(m, argv);//3 27 }

注释1处className为“com.android.server.SystemServer",因此通过反射返回的cl为SystemServer类。注释2处找到SystemServer中的main函数。在注释3处将找到的main函数传入到MethodAndArgsCaller异常中并抛出该异常。截获MethodAndArgsCaller异常的代码在ZygoteInit.java的main函数中,如下所示。

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

1 public static void main(String argv[]) { 2 ... 3 closeServerSocket(); 4 } catch (MethodAndArgsCaller caller) { 5 caller.run();//1 6 } catch (RuntimeException ex) { 7 Log.e(TAG, "Zygote died with exception", ex); 8 closeServerSocket(); 9 throw ex; 10 } 11 }

在注释1处调用了MethodAndArgsCaller的run函数:

1 public void run() { 2 try { 3 mMethod.invoke(null, new Object[] { mArgs }); 4 } catch (IllegalAccessException ex) { 5 ... 6 } 7 } 8}

这里mMethod指的就是SystemServer的main函数,因此main函数被动态调用。

3.解析SyetemServer进程

我们先来查看SystemServer的main函数: frameworks/base/services/java/com/android/server/SystemServer.java

1 public static void main(String[] args) { 2 new SystemServer().run(); 3 }

main函数中只调用了SystemServer的run函数,如下所示。

1 private void run() { 2 ... 3 System.loadLibrary("android_servers");//1 4 ... 5 mSystemServiceManager = new SystemServiceManager(mSystemContext);//2 6 LocalServices.addService(SystemServiceManager.class, mSystemServiceManager); 7 ... 8 try { 9 Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices"); 10 startBootstrapServices();//3 11 startCoreServices();//4 12 startOtherServices();//5 13 } catch (Throwable ex) { 14 Slog.e("System", "******************************************"); 15 Slog.e("System", "************ Failure starting system services", ex); 16 throw ex; 17 } finally { 18 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); 19 } 20 ... 21 }

run函数代码很多,关键就是在注释1处加载了libandroid_servers.so。接下来在注释2处创建SystemServiceManager,它会对系统的服务进行创建、启动和生命周期管理。启动系统的各种服务,在注释3中的startBootstrapServices函数中用SystemServiceManager启动了ActivityManagerService、PowerManagerService、PackageManagerService等服务。在注释4处的函数中则启动了BatteryService、UsageStatsService和WebViewUpdateService。注释5处的startOtherServices函数中则启动了CameraService、AlarmManagerService、VrManagerService等服务,这些服务的父类为SystemService。从注释3、4、5的函数可以看出,官方把系统服务分为了三种类型,分别是引导服务、核心服务和其他服务,其中其他服务为一些非紧要和一些不需要立即启动的服务。系统服务大约有80多个,这里列出部分系统服务以及它们的作用如下表所示:

引导服务作用
Installer系统安装apk时的一个服务类,启动完成Installer服务之后才能启动其他的系统服务
ActivityManagerService负责四大组件的启动、切换、调度。
PowerManagerService计算系统中和Power相关的计算,然后决策系统应该如何反应
LightsService管理和显示背光LED
DisplayManagerService用来管理所有显示设备
UserManagerService多用户模式管理
SensorService为系统提供各种感应器服务
PackageManagerService用来对apk进行安装、解析、删除、卸载等等操作
核心服务
BatteryService管理电池相关的服务
UsageStatsService收集用户使用每一个APP的频率、使用时常
WebViewUpdateServiceWebView更新服务
其他服务
CameraService摄像头相关服务
AlarmManagerService全局定时器管理服务
InputManagerService管理输入事件
WindowManagerService窗口管理服务
VrManagerServiceVR模式管理服务
BluetoothService蓝牙管理服务
NotificationManagerService通知管理服务
DeviceStorageMonitorService存储相关管理服务
LocationManagerService定位管理服务
AudioService音频相关管理服务
.......

比如要启动PowerManagerService则会调用如下代码:

1mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

SystemServiceManager的startService函数启动了PowerManagerService,startService函数如下所示。

frameworks/base/services/core/java/com/android/server/SystemServiceManager.java

1 public <T extends SystemService> T startService(Class<T> serviceClass) { 2 ... 3 final T service; 4 try { 5 Constructor<T> constructor = serviceClass.getConstructor(Context.class); 6 service = constructor.newInstance(mContext);//1 7 } catch (InstantiationException ex) { 8 throw new RuntimeException("Failed to create service " + name 9 + ": service could not be instantiated", ex); 10 } 11... 12 // Register it. 13 mServices.add(service);//2 14 // Start it. 15 try { 16 service.onStart(); 17 } catch (RuntimeException ex) { 18 throw new RuntimeException("Failed to start service " + name 19 + ": onStart threw an exception", ex); 20 } 21 return service; 22 } finally { 23 Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER); 24 } 25 }

注释1处的代码用来创建SystemService,这里的SystemService是PowerManagerService,在注释2处将PowerManagerService添加到mServices中,这里mServices是一个存储SystemService类型的ArrayList。接着调用PowerManagerService的onStart函数启动PowerManagerService并返回,这样就完成了PowerManagerService启动的过程。 除了用mSystemServiceManager的startService函数来启动系统服务外,也可以通过如下形式来启动系统服务,以PackageManagerService为例:

1 mPackageManagerService = PackageManagerService.main(mSystemContext, installer, 2 mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);

直接调用了PackageManagerService的main函数: frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

1public static PackageManagerService main(Context context, Installer installer, 2 boolean factoryTest, boolean onlyCore) { 3 // Self-check for initial settings. 4 PackageManagerServiceCompilerMapping.checkProperties(); 5 PackageManagerService m = new PackageManagerService(context, installer, 6 factoryTest, onlyCore);//1 7 m.enableSystemUserPackages(); 8 // Disable any carrier apps. We do this very early in boot to prevent the apps from being 9 // disabled after already being started. 10 CarrierAppUtils.disableCarrierAppsUntilPrivileged(context.getOpPackageName(), m, 11 UserHandle.USER_SYSTEM); 12 ServiceManager.addService("package", m);//2 13 return m; 14}

注释1处直接创建PackageManagerService并在注释2处将PackageManagerService注册到ServiceManager中,ServiceManager用来管理系统中的各种Service,用于系统C/S架构中的Binder机制通信:Client端要使用某个Service,则需要先到ServiceManager查询Service的相关信息,然后根据Service的相关信息与Service所在的Server进程建立通讯通路,这样Client端就可以使用Service了。还有的服务是直接注册到ServiceManager中的,如下所示。

frameworks/base/services/java/com/android/server/SystemServer.java

1 telephonyRegistry = new TelephonyRegistry(context); 2 ServiceManager.addService("telephony.registry", telephonyRegistry);

4.总结SyetemServer进程

SyetemServer在启动时做了如下工作: 1.启动Binder线程池,这样就可以与其他进程进行通信。 2.创建SystemServiceManager用于对系统的服务进行创建、启动和生命周期管理。 3.启动各种系统服务。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

Android系统启动流程(四)Launcher启动过程与系统启动流程

Android框架层Android系统启动categories:Android框架层本文首发于微信公众号「刘望舒」前言此前的文章我们学习了init进程、Zygote进程和SyetemServer进程的启动过程,这一篇文章我们就来学习Android系统启动流程的最后一步:Launcher的启动流程,并结合本系列的前三