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> [--] &lt;start class name&gt;  &lt;args&gt;

* </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分析的更多相关文章

  1. Android系统启动分析(Init->Zygote->SystemServer->Home activity)

    整个Android系统的启动分为Linux Kernel的启动和Android系统的启动.Linux Kernel启动起来后,然后运行第一个用户程序,在Android中就是init程序. ------ ...

  2. SystemServer相关

    SystemServer分析 由Zygote通过Zygote.forkSystemServer函数fork出来的.此函数是一个JNI函数,实现在dalvik_system_Zygote.c中. 1.S ...

  3. [深入理解Android卷一全文-第四章]深入理解zygote

    由于<深入理解Android 卷一>和<深入理解Android卷二>不再出版,而知识的传播不应该由于纸质媒介的问题而中断,所以我将在CSDN博客中全文转发这两本书的所有内容. ...

  4. 安卓学习资料推荐《深入理解Android:卷2》下载

    下载地址:百度云下载地址 编辑推荐 <深入理解Android:卷2>编辑推荐:经典畅销书<深入理解Android:卷I>姊妹篇,51CTO移动开发频道和开源中国社区一致鼎力推荐 ...

  5. Android5 Zygote 与 SystemServer 启动流程分析

    Android5 Zygote 与 SystemServer 启动流程分析 Android5 Zygote 与 SystemServer 启动流程分析 前言 zygote 进程 解析 zygoterc ...

  6. Android5.0L下因sensorservice crash导致systemserver重新启动的第二种场景分析

    一.出问题的场景 1.Sensorservice线程正在处理compass sensor事件的过程中.检查了一次buffer的指针的有效性,并在稍后会传递到AKM获取数据的函数接口中使用 2.Sens ...

  7. PackageManager源码分析

    在android 4.4源码上进行的分析. 一.PackageManager如何产生的? 我们平时在代码中使用的context.getPackageManager() 那么这个PackageManag ...

  8. Android WIFI 分析(一)

    本文基于<深入理解Android WiFi NFC和GPS 卷>和 Android N 代码结合分析   WifiService 是 Frameworks中负责wifi功能的核心服务,它主 ...

  9. 【Bugly干货分享】手把手教你逆向分析 Android 程序

    很多人写文章,喜欢把什么行业现状啊,研究现状啊什么的写了一大通,感觉好像在写毕业论文似的,我这不废话,先直接上几个图,感受一下. 第一张图是在把代码注入到地图里面,启动首页的时候弹出个浮窗,下载网络的 ...

随机推荐

  1. Mac格式化fat32格式

    好的,格式化硬盘可以使用电脑内置的磁盘工具来格式. 在 LaunchPad 中的 实用工具 或 其它 找到 磁盘工具 打开磁盘工具后,找到你的移动硬盘. (这里以我的希捷移动盘来示例) 非常容易找到, ...

  2. string 的用法

    上次,我在" Anton And Danik "中为大家介绍了 string 的部分用法 今天,我就再来为大家介绍一下 string 的其他用法 : ( 有可能已经讲过了,不要介意 ...

  3. 解决windows系统下打开应用弹出丢失libmysql.dll的问题

    只要把下载libmysql.dll,放到exe应用程序的所在目录,就可以运行,libmysql.dll有32位和64位版本,可以分别测试一下行不行,如果不行在换一个 版本试试.libmysql.dll ...

  4. matplot绘图(五)

    b3D图形绘制 # 导包:from mpl_toolkits.mplot3d.axes3d import Axes3Dimport matplotlib.pyplot as plt%matplotli ...

  5. Unity基础-脚本的优化

    脚本的优化 object pool 避免频繁的内存分配和gc噩梦(字符串相加?) 是否有必要都写在update里?分帧? 需要的只取一次 使用editor内赋值,而不是find 复杂的物理 复杂的数学 ...

  6. PHP做ERP, CRM, CMS系统需要注意哪些地方

    php作为二次开发弱类型语言, 可读性, 可视度都是比较高的. 在很多人眼里, 也许php只能做一些web应用开发, 比如某个公司的网站, 某个公司的网站后台, 其实,我可以告诉大家, php不比任何 ...

  7. 《linux设备驱动开发详解》笔记——18 ARM linux设备树

    18.1 设备树的起源 linux 2.6及之前,大量板级信息被硬编码到内核里,十分庞大,大量冗余代码: linux 2.6之前,引入了设备树: 设备树源于OpenFirmware,描述硬件的数据结构 ...

  8. 通过代码链接ftp上传下载删除文件

    因为我的项目是Maven项目,首先要导入一个Maven库里的包:pom.xml <dependency>            <groupId>com.jcraft</ ...

  9. CodeForces - 948C Producing Snow(优先队列)

    题意: n天. 每天你会堆一堆雪,体积为 v[i].每天都有一个温度 t[i] 所有之前堆过的雪在第 i 天体积都会减少 t[i] . 输出每天融化了的雪的体积. 这个题的正解我怎么想都很难理解,但是 ...

  10. POJ:3041-Asteroids(匈牙利算法模板)

    传送门:http://poj.org/problem?id=3041 Asteroids Time Limit: 1000MS Memory Limit: 65536K Description Bes ...