System Server进程是如何创建的
从上一篇Zygote进程启动过程中,可以看到System Server进程是在Zygote进程中创建出来的。查看ZygoteInit.java
类,路径是/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
,找到main方法,可以看到在main方法中启动了System Server。
public static void main(String argv[]) {
// 代码省略....
if (startSystemServer) {
startSystemServer(abiList, socketName, zygoteServer);
}
// 代码省略....
}
在ZygoteInit.java
类找到startSystemServer
方法,如下,通过注释可以看到这个方法主要作用是:准备参数和孵化系统服务进程。
/**
* Prepare the arguments and fork for the system server process.
* 准备参数和孵化系统服务进程
*/
private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
throws Zygote.MethodAndArgsCaller, RuntimeException {
long capabilities = posixCapabilitiesAsBits(
OsConstants.CAP_IPC_LOCK,
OsConstants.CAP_KILL,
OsConstants.CAP_NET_ADMIN,
OsConstants.CAP_NET_BIND_SERVICE,
OsConstants.CAP_NET_BROADCAST,
OsConstants.CAP_NET_RAW,
OsConstants.CAP_SYS_MODULE,
OsConstants.CAP_SYS_NICE,
OsConstants.CAP_SYS_PTRACE,
OsConstants.CAP_SYS_TIME,
OsConstants.CAP_SYS_TTY_CONFIG,
OsConstants.CAP_WAKE_ALARM
);
/* Containers run without this capability, so avoid setting it in that case */
if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {
capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);
}
/* Hardcoded command line to start the system server */
// 1、准备fork系统服务的参数
String args[] = {
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,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 */
// 2、通过Zygote来fork系统服务的进程
pid = Zygote.forkSystemServer(
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}
/* For child process */
// 3、如果pid为0,表示在子线程中执行
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}
// 4、关闭复制的zygote进程的Socket
zygoteServer.closeServerSocket();
// 5、在子进程中执行操作
handleSystemServerProcess(parsedArgs);
}
return true;
}
通过代码分析,startSystemServer
方法中主要做了以下几件事:
- 准备fork系统服务的参数
- 通过Zygote来fork系统服务的进程
- 如果pid为0,表示在子线程中执行,即在fork出的system server进程中执行相关逻辑,执行方法是
handleSystemServerProcess
。下面就分析这个方法主要做了哪些事情。 - SyetemServer进程是复制了Zygote进程的地址空间,因此也会得到Zygote进程创建的Socket,这个Socket对于SyetemServer进程没有用处,所以调用closeServerSocket()关闭它。
System Server创建后做了哪些事
一、ZygoteInit.java
类中的方法handleSystemServerProcess
从上一个标题得知,系统服务创建之后,执行了handleSystemServerProcess
方法,在该类中找到该方法,如下所示:
/**
* Finish remaining work for the newly forked system server process.
*/
private static void handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs)throws Zygote.MethodAndArgsCaller {
// set umask to 0077 so new files and directories will default to owner-only permissions.
Os.umask(S_IRWXG | S_IRWXO);
// 1、niceName 其实就是system server的进程名system_server
if (parsedArgs.niceName != null) {
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 {
File profileDir = Environment.getDataProfilesDePackageDirectory(
Process.SYSTEM_UID, "system_server");
File profile = new File(profileDir, "primary.prof");
profile.getParentFile().mkdirs();
profile.createNewFile();
String[] codePaths = systemServerClasspath.split(":");
VMRuntime.registerAppInfo(profile.getPath(), codePaths);
} catch (Exception e) {
Log.wtf(TAG, "Failed to set up system server profile", e);
}
}
}
if (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;
}
// 2、启动应用进程
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
VMRuntime.getCurrentInstructionSet(), null, args);
} else {
ClassLoader cl = null;
if (systemServerClasspath != null) {
cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
Thread.currentThread().setContextClassLoader(cl);
}
/*
* Pass the remaining arguments to SystemServer.
* 3、调用zygoteInit方法,进一步启动SystemServer
*/
ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
}
}
- niceName 其实就是system server的进程名system_server
- 启动应用进程
- 由于parsedArgs.invokeWith属性默认为null,最后调用ZygoteInit.zygoteInit来进一步启动SystemServer。
二、ZygoteInit.java
类中的方法zygoteInit
public static final void zygoteInit(int targetSdkVersion, String[] argv,ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
// 1、重定向Log输出
RuntimeInit.redirectLogStreams();
// 2、初始化运行环境
RuntimeInit.commonInit();
///3、调用zygote的native方法启动Binder线程池
ZygoteInit.nativeZygoteInit();
// 4、调用应用入口函数
RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
zygoteInit主要做了以下几件事:
- 重定向Log输出
- 初始化运行环境
- 调用zygote的native方法启动Binder线程池
- 调用
RuntimeInit.applicationInit
方法启动应用程序
1、先查看zygote的native方法是如何启动Binder线程池的
找到zygote的native方法类AndroidRuntime.cpp
,路径是:/frameworks/base/core/jni/AndroidRuntime.cpp
通过注册方法数组找到native方法com_android_internal_os_ZygoteInit_nativeZygoteInit
int register_com_android_internal_os_ZygoteInit(JNIEnv* env)
{
const JNINativeMethod methods[] = {
{ "nativeZygoteInit", "()V",
(void*) com_android_internal_os_ZygoteInit_nativeZygoteInit },
};
return jniRegisterNativeMethods(env, "com/android/internal/os/ZygoteInit",
methods, NELEM(methods));
}
找到
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}
这里调用了onZygoteInit()
方法,而gCurRuntime是AndroidRuntime类的指针,而上文提到到app_main.cpp(路径是frameworks/base/cmds/app_process/app_main.cpp)中定义了AppRuntime 类,继承于AndroidRuntime类,在AppRuntime类中的onZygoteInit方法中,调用了ProcessState
类的启动binder线程池的方法proc->startThreadPool();
。
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
找到ProcessState类,路径是/frameworks/native/libs/binder/ProcessState.cpp
,找到startThreadPool
方法,如下:
void ProcessState::startThreadPool()
{
AutoMutex _l(mLock);
if (!mThreadPoolStarted) {
mThreadPoolStarted = true;
spawnPooledThread(true);
}
}
其中有个判断是变量,由于支持Binder通信的进程中都有一个ProcessState类,它里面有一个mThreadPoolStarted 变量,来表示Binder线程池是否已经被启动过,默认值为false。在每次调用这个函数时都会先去检查这个标记,从而确保Binder线程池只会被启动一次。
如果Binder线程池未被启动则设置mThreadPoolStarted为true,最后调用spawnPooledThread函数来创建线程池中的第一个线程,也就是线程池的main线程。
找到spawnPooledThread
方法,如下,,如果线程池启动则创建一个PoolThread,实际上Binder线程为一个PoolThread,然后调用run方法来运行。
void ProcessState::spawnPooledThread(bool isMain)
{
if (mThreadPoolStarted) {
String8 name = makeBinderThreadName();
ALOGV("Spawning new pooled thread, name=%s\n", name.string());
sp<Thread> t = new PoolThread(isMain);
t->run(name.string());
}
}
找到类PoolThread
,PoolThread类继承了Thread类。threadLoop方法中调用IPCThreadState的joinThreadPool函数,将当前线程注册到Binder驱动程序中,这样我们创建的线程就加入了Binder线程池中,这样新创建的SyetemServer进程就支持Binder进程间通信了。
class PoolThread : public Thread
{
public:
explicit PoolThread(bool isMain)
: mIsMain(isMain)
{
}
protected:
virtual bool threadLoop()
{
IPCThreadState::self()->joinThreadPool(mIsMain);
return false;
}
const bool mIsMain;
};
注意:
1、保证同一进程只有一个ProcessState实例,且只有在ProcessState对象建立时才打开Binder设备以及做内存映射
ProcessState::ProcessState(const char *driver)
: mDriverName(String8(driver))
, mDriverFD(open_driver(driver))
, mVMStart(MAP_FAILED)
, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
, mExecutingThreadsCount(0)
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
, mStarvationStartTimeMs(0)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
{
if (mDriverFD >= 0) {
// mmap the binder, providing a chunk of virtual address space to receive transactions.
mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
// *sigh*
ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
close(mDriverFD);
mDriverFD = -1;
mDriverName.clear();
}
}
LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating.");
}
ProcessState::~ProcessState()
{
if (mDriverFD >= 0) {
if (mVMStart != MAP_FAILED) {
// 内存映射
munmap(mVMStart, BINDER_VM_SIZE);
}
close(mDriverFD);
}
mDriverFD = -1;
}
};
2、ProcessState是负责打开Binder节点并做mmap映射并向上层提供IPC服务,IPCThreadState是负责与Binder驱动进行具体的命令交互。
open_driver方法实现打开Binder驱动并进行具体的命令交互。
static int open_driver(const char *driver)
{
int fd = open(driver, O_RDWR | O_CLOEXEC);
if (fd >= 0) {
int vers = 0;
status_t result = ioctl(fd, BINDER_VERSION, &vers);
if (result == -1) {
ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
close(fd);
fd = -1;
}
if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
ALOGE("Binder driver protocol(%d) does not match user space protocol(%d)! ioctl() return value: %d",
vers, BINDER_CURRENT_PROTOCOL_VERSION, result);
close(fd);
fd = -1;
}
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
if (result == -1) {
ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
}
} else {
ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno));
}
return fd;
}
2、调用RuntimeInit.applicationInit
方法启动应用程序
RuntimeInit.java
类,路径是/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
,找到applicationInit
方法如下:
protected static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
throws Zygote.MethodAndArgsCaller {
// If the application calls System.exit(), terminate the process
// immediately without running any shutdown hooks. It is not possible to
// shutdown an Android application gracefully. Among other things, the
// Android runtime shutdown hooks close the Binder driver, which can cause
// leftover running threads to crash before the process actually exits.
nativeSetExitWithoutCleanup(true);
// We want to be fairly aggressive about heap utilization, to avoid
// holding on to a lot of memory that isn't needed.
// 初始化虚拟机环境
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
final Arguments args;
try {
args = new Arguments(argv);
} catch (IllegalArgumentException ex) {
Slog.e(TAG, ex.getMessage());
// let the process exit
return;
}
// The end of of the RuntimeInit event (see #zygoteInit).
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
// Remaining arguments are passed to the start class's static main
// 调用main方法
invokeStaticMain(args.startClass, args.startArgs, classLoader);
}
从代码可以看到主要做了两件事,一个是初始化虚拟机环境,一个是调用了invokeStaticMain
方法,找到该方法如下:
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
throws Zygote.MethodAndArgsCaller {
Class<?> cl;
try {
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
throw new RuntimeException(
"Missing static main on " + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException(
"Problem getting static main on " + className, ex);
}
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException(
"Main method is not public and static on " + className);
}
/*
* This throw gets caught in ZygoteInit.main(), which responds
* by invoking the exception's run() method. This arrangement
* clears up all the stack frames that were required in setting
* up the process.
*/
throw new Zygote.MethodAndArgsCaller(m, argv);
}
这里主要是通过反射的方式获取SystemServer类实例,classsName就是com.android.server.SystemServer
(见上面ZygoteInit.java
类中startSystemServer
方法中配置的启动参数),最后执行创建Zygote.MethodAndArgsCaller(m, argv)
类。找到该类如下:
public static class MethodAndArgsCaller extends Exception
implements Runnable {
/** method to call */
private final Method mMethod;
/** argument array */
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
Throwable cause = ex.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
throw (Error) cause;
}
throw new RuntimeException(ex);
}
}
}
这里就是 通过反射调用SystemServer.java
的main方法,到这,zygote进程就成功fork出system_server进程,并调用了SystemServer.java
的main方法。
接着分析SystemServer.java
的main方法,类路径是:/frameworks/base/services/java/com/android/server/SystemServer.java
,方法实现如下:
public static void main(String[] args) {
new SystemServer().run();
}
找到run方法如下:
private void run() {
try {
// ......
// 1、启动looper循环
Looper.prepareMainLooper();
// Initialize native services.
// 2、初始化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.
///3、创建SystemServiceManager,它会对系统的服务进行创建、启动和生命周期管理。启动系统的各种服务。
mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Prepare the thread pool for init tasks that can be parallelized
SystemServerInitThreadPool.get();
} finally {
traceEnd(); // InitBeforeStartServices
}
// Start services.
try {
traceBeginAndSlog("StartServices");
// 4、启动引导服务
startBootstrapServices();
///5、启动核心服务
startCoreServices();
// 6、启动其他服务
startOtherServices();
SystemServerInitThreadPool.shutdown();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
traceEnd();
}
// ......
// Loop forever.
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
从run方法中可以看到主要做了以下几件事:
- 启动服务都是在Looper循环中执行。system_server进程中的主线程是不能退出的,一旦退出子线程也会退出,所以进入loop循环。
- 初始化libandroid_servers.so库,system_server进程中启动的服务器的native代码都在这个共享库中。
- 创建SystemServiceManager,它会对系统的服务进行创建、启动和生命周期管理。启动系统的各种服务。
- 启动引导服务
- 启动核心服务
- 启动其他服务
这里把系统服务分为了三种类型,分别是引导服务、核心服务和其他服务,其中其他服务为一些非紧要和一些不需要立即启动的服务。系统服务大约有80多个,这里列出部分系统服务以及它们的作用:
引导服务 | 作用 |
---|---|
Installer | 系统安装apk时的一个服务类,启动完成Installer服务之后才能启动其他的系统服务 |
ActivityManagerService | 负责四大组件的启动、切换、调度 |
PowerManagerService | 计算系统中与Power相关的计算,然后决策系统应该如何反应 |
LightsService | 管理和显示背光LED |
DisplayManagerService | 管理和显示背光LED |
UserManagerService | 多用户模式管理 |
PackageManagerService | 用来对apk进行安装、解析、删除、卸载等操作 |
OverlayManagerService | OverlayManagerService(OMS)可以在运行时动态替换res等资源 |
SensorService | 为系统提供各种感应器服务,调用的是native方法 |
核心服务 | 作用 |
---|---|
DropBoxManagerService | DropBoxManagerService(简称DBMS) 记录着系统关键log信息,主要功能用于Debug调试。 |
BatteryService | 管理电池相关的服务 |
UsageStatsService | 收集用户使用每一个APP的频率、使用时间 |
WebViewUpdateService | webview更新服务 |
其他服务 | 作用 |
---|---|
CameraService | 摄像头相关服务 |
AlarmManagerService | 全局定时器管理服务 |
InputManagerService | 管理输入事件服务 |
WindowManagerService | 窗口管理服务 |
VrManagerService | VR模式管理服务 |
BluetoothService | 蓝牙管理服务 |
NotificationManagerService | 通知栏管理服务,Android中的通知栏和状态栏在一起,只是界面上前者在左边,后者在右边 |
DeviceStorageMonitorService | 存储相关管理服务 |
LocationManagerService | 地理位置管理服务 |
AudioService | 音频相关管理服务 |
AccessibilityManagerService | 辅助管理服务 |
ContentService | ContentProvider服务,提供跨进程数据交换 |
NetworkManagementService | 网络管理服务 |
问题与思考
1、System Server是什么?
System Server是Android系统的核心,是 Android JAVA 层的系统服务模块,这个模块主要功能就是管理供 Android 应用开发的各种系统服务,比如AMS、PMS、WMS等服务. 在Dalvik虚拟机启动后立即开始初始化和运行。其它的系统服务在System Server进程的环境中运行。
2、System Server主要做了哪些事情?
- 启动binder线程池
- 启动各种服务
3、System Server中启动binder线程池作用?
因为system_server进程中许多服务要与其他进程进行通信,比如要与应用进程进行通信,所以要启动binder机制进行跨进程通信。
4、系统服务都运行在哪些线程中?
主线程:负责Message通信。
工作线程:
- 独有线程,AMS、PMS、WMS
- 公用线程DisplayThread、FgThread、IoThread、UiThread
- 跨进程通信都在binder线程,所以系统服务们也在binder线程中
5、系统服务们如何解决相互依赖?
分批启动和分阶段启动,启动之后再去调用。