SystemServer分析
1 SystemServer分析
SystemServer的进程名就是前面所说的“system_server”,是zygote进程“app_process”fork出来的第一个子嗣,其重要性不言而喻。下面我们简称其为SS。
1.1 SS的诞生
先回顾一下SS是如何创建的:
|
/*在zygoteinit.java的startsystemserver方法中*/ String args[] = { "--setuid=1000", "--setgid=1000", "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007", "--capabilities=" + capabilities + "," + capabilities, "--runtime-init", "--nice-name=system_server", "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 */ pid = Zygote.forkSystemServer( //调用此函数创建SS! parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } |
下面看看forkSystemServer函数的具体内容 :
|
/*在Dalvik_dalvik_system_Zygote.cpp中)*/ /* * native public static int nativeForkSystemServer(int uid, int gid, * int[] gids, int debugFlags, int[][] rlimits, * long permittedCapabilities, long effectiveCapabilities); */ static void Dalvik_dalvik_system_Zygote_forkSystemServer( const u4* args, JValue* pResult) { pid_t pid; /*根据参数fork一个子进程SS,并返回子进程的PID*/ pid = forkAndSpecializeCommon(args, true, true); /* The zygote process checks whether the child process has died or not. */ if (pid > 0) { int status; ALOGI("System server process %d has been created", pid); gDvm.systemServerPid = pid; //保存SS的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. */ /*函数退出前需要先检查创建的子进程SS是否退出了*/ if (waitpid(pid, &status, WNOHANG) == pid) { //如果SS退出了,那么zygote就自杀~ ALOGE("System server process %d has died. Restarting Zygote!", pid); kill(getpid(), SIGKILL); } } RETURN_INT(pid); } |
下面在看看forkAndSpecializeCommon函数主要完成两个工作:1,根据传入的参数对子进程做一些处理,如设置进程名,各种id等;2,就是调用很重要的信号处理函数setSignalHandler()。
该函数代码如下:
|
static void setSignalHandler() { int err; struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = sigchldHandler; //关联信号处理函数 err = sigaction (SIGCHLD, &sa, NULL); //设置信号处理函数,该信号是子进程死亡的信号 if (err < 0) { ALOGW("Error setting SIGCHLD handler: %s", strerror(errno)); } } /*再看sigchldHandler函数,此函数由zygote在fork子进程之前调用!*/ static void sigchldHandler(int s) { pid_t pid; int status; while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { /* LOG死亡子进程的状态,以便调试*/ if (WIFEXITED(status)) { if (WEXITSTATUS(status)) { ALOG(LOG_DEBUG, ZYGOTE_LOG_TAG, "Process %d exited cleanly (%d)", (int) pid, WEXITSTATUS(status)); } else { IF_ALOGV(/*should use ZYGOTE_LOG_TAG*/) { ALOG(LOG_VERBOSE, ZYGOTE_LOG_TAG, "Process %d exited cleanly (%d)", (int) pid, WEXITSTATUS(status)); } } } else if (WIFSIGNALED(status)) { if (WTERMSIG(status) != SIGKILL) { ALOG(LOG_DEBUG, ZYGOTE_LOG_TAG, "Process %d terminated by signal (%d)", (int) pid, WTERMSIG(status)); } else { IF_ALOGV(/*should use ZYGOTE_LOG_TAG*/) { ALOG(LOG_VERBOSE, ZYGOTE_LOG_TAG, "Process %d terminated by signal (%d)", (int) pid, WTERMSIG(status)); } } #ifdef WCOREDUMP if (WCOREDUMP(status)) { ALOG(LOG_INFO, ZYGOTE_LOG_TAG, "Process %d dumped core", (int) pid); } #endif /* ifdef WCOREDUMP */ } /*如果崩溃的子进程是SS,那么zygote就自杀,然后由init进程重新fork zygote进程,进而重启SS进程*/ if (pid == gDvm.systemServerPid) { ALOG(LOG_INFO, ZYGOTE_LOG_TAG, "Exit zygote because system server (%d) has terminated", (int) pid); kill(getpid(), SIGKILL); } } if (pid < 0) { ALOG(LOG_WARN, ZYGOTE_LOG_TAG, "Zygote SIGCHLD error in waitpid: %s",strerror(errno)); } } |
从上面的分析可以看出SS同zygote进程同生共死,可见SS的重要性!下面开始分析SS在Android系统中到底扮演者什么样的角色。
1.2 SS的使命
SS进程诞生后,就同zygote进程分道扬镳了。它有了自己的使命,那么它的使命是什么呢?这需要我们会到zygotinit.java文件中的startSystemServer方法中:
|
try { …… pid = Zygote.forkSystemServer(…); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } /* For child process */ if (pid == 0) { //这里就是SS的使命! handleSystemServerProcess(parsedArgs); } /* handleSystemServerProcess 的详细代码如下*/ private static void handleSystemServerProcess( ZygoteConnection.Arguments parsedArgs) throws ZygoteInit.MethodAndArgsCaller { closeServerSocket(); //首先关闭从zygote继承来的socket //然后将umask值设为0077,这样的话新创建的文件和目录在默认情况下就//只有创建用户本身拥有读写权限了~ Libcore.os.umask(S_IRWXG | S_IRWXO); if (parsedArgs.niceName != null) { Process.setArgV0(parsedArgs.niceName); //有昵称就设置昵称 } if (parsedArgs.invokeWith != null) { WrapperInit.execApplication(parsedArgs.invokeWith, parsedArgs.niceName, parsedArgs.targetSdkVersion, null, parsedArgs.remainingArgs); } else { /*调用zygoteInit函数,并将主要的参数传递给SS*/ RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs); } } |
现在SS就进入到RuntimeInit类中了,zygoteInit的代码在RuntimeInit.java中,详细代码如下:
|
/** * 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> * * Current recognized args: * <ul> * <li> <code> [--] <start class name> <args> * </ul> * * @param targetSdkVersion target SDK version * @param argv arg strings */ public static final void zygoteInit(int targetSdkVersion, String[] argv) throws ZygoteInit.MethodAndArgsCaller { if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote"); /*Redirect System.out and System.err to the Android log.分别对应log.info和log.warm*/ redirectLogStreams(); /*做一些常规初始化操作:很简单,可以看源代码中的注释*/ commonInit(); /*key1 native层的初始化*/ nativeZygoteInit(); /*key2 应用层的初始化,其实主要是通过调用invokeStaticMain函数来调用com.android.server.SystemServer类的main函数*/ applicationInit(targetSdkVersion, argv); } |
下面开始详细分析key1和key2。
1、nativeZygoteInit分析
nativeZygoteInit是一个native函数,它的实现在androidRuntime.cpp中
|
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz) { gCurRuntime->onZygoteInit(); } gCurRuntime 是什么呢?回顾app_process(zygote)的main函数中有: AppRuntime runtime; AppRuntime类的定义: class AppRuntime : public AndroidRuntime // AppRuntime继承于AndroidRuntime 而gCurRuntime定义如下: static AndroidRuntime* gCurRuntime = NULL; //说明 gCurRuntime是一个AndroidRuntime类对象 AndroidRuntime的构造函数如下: AndroidRuntime::AndroidRuntime() : mExitWithoutCleanup(false) { //图形相关的初始化,skia库初始化。 SkGraphics::Init(); SkImageDecoder::SetDeviceConfig(SkBitmap::kRGB_565_Config); SkImageRef_GlobalPool::SetRAMBudget(512 * 1024); mOptions.setCapacity(20); assert(gCurRuntime == NULL); gCurRuntime = this; // gCurRuntime被设置为AndroidRuntime对象自己! } |
由于SS是从zygote fork出来的,所以它也拥有zygote进程中定义的这个gCurRuntime对象,那么onZygoteInit有什么作用呢?它的代码在App_main.cpp中:
|
virtual void onZygoteInit() { atrace_set_tracing_enabled(true); //这个函数与binder有关,暂时不细究~ sp<ProcessState> proc = ProcessState::self(); ALOGV("App process: starting thread pool.\n"); proc->startThreadPool(); //启动一个线程,用于Binder通信。 } |
一言以蔽之,SS调用nativeZygoteInit后,将于Binder通信系统建立联系,这样SS就能够使用binder了。关于Binder的知识,将在后面详细介绍,这里不过多关注。
2、applicationInit分析
applicationInit主要是完成SS的应用层(java层)的初始化工作,该函数的核心功能在invokeStaticMain函数中:
|
private static void invokeStaticMain(String className, String[] argv) throws ZygoteInit.MethodAndArgsCaller { //传递进来的参数className = “com.android.server.SystemServer” Class<?> cl; try { cl = Class.forName(className); } 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. */ /*重点来了!!!这里竟然抛出了一个异常!从源代码的注释可以知道,这个异常被ZygoteInit.main()截获(注意:我们此时是在SS进程中),然后调用该异常的run函数。 */ throw new ZygoteInit.MethodAndArgsCaller(m, argv); } /*回到zygoteinit.java的main函数看一下这个run 函数的功能*/ public void run() { try { /*这个mMethod是com.android.server.SystemServer的main函数*/ mMethod.invoke(null, new Object[] { mArgs }); } catch (IllegalAccessException ex) { …… } |
可以看出,invokeStaticMain抛出异常后会导致zygote进程调用com.android.server.SystemServer的main函数。那么为什么不直接在invokeStaticMain里面调用,转而使用这种方法呢?这个涉及到堆栈调用相关的只是,笔者还没弄明白,暂时搁置~
3、SS的真面目
Zygoteinit分裂产生的SS其实就是为了调用com.android.server.SystemServer的main函数!那么我们来看一看这个main函数到底做了什么:
|
public static void main(String[] args) { …….. // Mmmmmm... more memory!这尼玛是在搞笑? dalvik.system.VMRuntime.getRuntime().clearGrowthLimit(); …… //加载libandroid_servers.so库 System.loadLibrary("android_servers"); Slog.i(TAG, "Entered the Android system server!"); // 调用native函数,初始化native服务,其实就完成一个功能: 判断服务是否为sensor服务,如果是,就启动之。 nativeInit(); // This used to be its own separate thread, but now it is // just the loop we run on the main thread. ServerThread thr = new ServerThread(); //创建一个服务线程 thr.initAndLoop(); //重点在这个函数! } } |
initAndLoop函数完成了SS真正的功能:启动系统各项重要的服务,然后此线程进行消息循环,接收和处理消息。
1.3 对SS的总结
SS的启动流程:
Zygoteinit调用startSystemServer创建System_server进程;SS调用hanleSystemServerProcess完成自己的使命;hanleSystemServerProcess抛出异常MethodAndArgsCaller,最终调用com.android.server.SystemServer的main函数;main函数创建一个ServerThread线程,再调用这个线程的initAndLoop函数;在这个initAndLoop函数中,启动系统各项重要的服务,并将该线程加入到Binder通信系统中,进行消息循环。
SystemServer分析的更多相关文章
- Android系统启动分析(Init->Zygote->SystemServer->Home activity)
整个Android系统的启动分为Linux Kernel的启动和Android系统的启动.Linux Kernel启动起来后,然后运行第一个用户程序,在Android中就是init程序. ------ ...
- SystemServer相关
SystemServer分析 由Zygote通过Zygote.forkSystemServer函数fork出来的.此函数是一个JNI函数,实现在dalvik_system_Zygote.c中. 1.S ...
- [深入理解Android卷一全文-第四章]深入理解zygote
由于<深入理解Android 卷一>和<深入理解Android卷二>不再出版,而知识的传播不应该由于纸质媒介的问题而中断,所以我将在CSDN博客中全文转发这两本书的所有内容. ...
- 安卓学习资料推荐《深入理解Android:卷2》下载
下载地址:百度云下载地址 编辑推荐 <深入理解Android:卷2>编辑推荐:经典畅销书<深入理解Android:卷I>姊妹篇,51CTO移动开发频道和开源中国社区一致鼎力推荐 ...
- Android5 Zygote 与 SystemServer 启动流程分析
Android5 Zygote 与 SystemServer 启动流程分析 Android5 Zygote 与 SystemServer 启动流程分析 前言 zygote 进程 解析 zygoterc ...
- Android5.0L下因sensorservice crash导致systemserver重新启动的第二种场景分析
一.出问题的场景 1.Sensorservice线程正在处理compass sensor事件的过程中.检查了一次buffer的指针的有效性,并在稍后会传递到AKM获取数据的函数接口中使用 2.Sens ...
- PackageManager源码分析
在android 4.4源码上进行的分析. 一.PackageManager如何产生的? 我们平时在代码中使用的context.getPackageManager() 那么这个PackageManag ...
- Android WIFI 分析(一)
本文基于<深入理解Android WiFi NFC和GPS 卷>和 Android N 代码结合分析 WifiService 是 Frameworks中负责wifi功能的核心服务,它主 ...
- 【Bugly干货分享】手把手教你逆向分析 Android 程序
很多人写文章,喜欢把什么行业现状啊,研究现状啊什么的写了一大通,感觉好像在写毕业论文似的,我这不废话,先直接上几个图,感受一下. 第一张图是在把代码注入到地图里面,启动首页的时候弹出个浮窗,下载网络的 ...
随机推荐
- HTTP、HTTP2.0、HTTPS、SPDY
本文原链接:https://cloud.tencent.com/developer/article/1082516 HTTP,HTTP2.0,SPDY,HTTPS你应该知道的一些事 1.web始祖HT ...
- CMDB资产采集方案
CMDB资产采集方案 CMDB 资产采集的方案总共有四种 Agent SSH类 Saltstack Puttet 方案设计,从性能上考虑 下面前三种是用Python开发的,目标是兼容三种采集方式的软件 ...
- CPP-基础:新标准 C++iostream
在新的标准 C++ iostream 库中: 1. open 函数不采用第三个参数(保护参数). 2. 无法从文件句柄创建流. 3. 除了几个例外,新的标准 C++ 库中的所有名称都在 std 命名空 ...
- Java Marker Interface
先看看什么是标记接口?标记接口有时也叫标签接口(Tag interface),即接口不包含任何方法. 在Java里很容易找到标记接口的例子,比如JDK里的Serializable接口就是一个标记接口. ...
- SC || Chapter7 健壮性和正确性
finally中语句不论有无异常都执行 若子类重写了父类方法,父类方法没有抛出异常,子类应自己处理全部异常而不再传播:子类从父类继承的方法不能增加或更改异常 判断checked和unchecked: ...
- lua调用java过程
在cocos2dx框架中,有继承好的luaj文件来方便我们去使用lua调用java底层代码,注意:luaj只能使用在安卓平台下,如果在平台下使用,会出错, 所以使用前需要加平台判断,方法 如下: lo ...
- 【模板】无旋Treap(FHQ)
如题,这是一个模板... #include <algorithm> #include <iostream> #include <cstring> #include ...
- Voyager的数据库操作与Bread Builder,解决国内打开网速超级慢的问题
Products表的创建: Bread Builder 伟大的XX封了谷哥,所以有关网站实在是打不开,正准备放弃的时候,突然发现问题了,对就是这个网站ajax.googleapis.com,由于调用的 ...
- How to Install PhantomJS on Ubuntu 16.04
Introduction PhantomJS is a scripted, headless browser that can be used for automating web page inte ...
- quartz 任务调度
quartz 设置参数, 获取参数 在job中使用spring注入的service对象 循环获取所有的job 删除job @PersistJobDataAfterExecution @Disallow ...