4.3 SystemServer分析

SystemServer的进程名实际上叫做“system_server”,这里我们可将其简称为SS。SS作为zygote的嫡长子,其重要性不言而喻。关于这一点,通过代码分析便可马上知晓。

4.3.1 SystemServer的诞生

我们先回顾一下SS是怎么创建的,代码如下所示:


String args[]={

"—setuid=1000",

"—setgid=1000",

"—setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,

3001,3002,3003",

"—capabilities=130104352,130104352",

"—runtime-init",

"—nice-name=system_server",

"com.android.server.SystemServer",

};

ZygoteConnection.Arguments parsedArgs=null;

int pid;

parsedArgs=new ZygoteConnection.Arguments(args);

int debugFlags=parsedArgs.debugFlags;

pid=Zygote.forkSystemServer(//调用forkSystemServer

parsedArgs.uid,parsedArgs.gid,

parsedArgs.gids,debugFlags,null);


从上面的代码中可以看出,SS是由Zygote通过Zygote.forkSystemServer函数fork诞生出来的。这里会有什么玄机吗?先一起来看看forkSystemServer的实现。它是一个native函数,实现在dalvik_system_Zygote.c中,如下所示:


[—>dalvik_system_Zygote.c]

static void Dalvik_dalvik_system_Zygote_forkSystemServer(

const u4args,JValuepResult)

{

pid_t pid;

//根据参数,fork一个子进程。

pid=forkAndSpecializeCommon(args);

if(pid>0){

int status;

gDvm.systemServerPid=pid;//保存system_server的进程id。

//函数退出前须先检查刚创建的子进程是否退出了。

if(waitpid(pid,&status,WNOHANG)==pid){

//如果system_server退出了,Zygote直接干掉了自己。

//看来Zygote和SS的关系异常紧密,简直是生死与共!

kill(getpid(),SIGKILL);

}

}

RETURN_INT(pid);

}


下面,再看看forkAndSpecializeCommon,代码如下所示:


[—>dalvik_system_Zygote.c]

static pid_t forkAndSpecializeCommon(const u4*args)

{

pid_t pid;

uid_t uid=(uid_t)args[0];

gid_t gid=(gid_t)args[1];

ArrayObjectgids=(ArrayObject)args[2];

u4 debugFlags=args[3];

ArrayObjectrlimits=(ArrayObject)args[4];

//设置信号处理,待会儿要看看这个函数。

setSignalHandler();

pid=fork();//fork子进程。

if(pid==0){

//要根据传入的参数对子进程做一些处理,例如设置进程名,设置各种id(用户id,组id等)。

}

……

}


最后看看setSignalHandler函数,它由Zygote在fork子进程前调用,代码如下所示:


[—>dalvik_system_Zygote.c]

static void setSignalHandler()

{

int err;

struct sigaction sa;

memset(&sa,0,sizeof(sa));

sa.sa_handler=sigchldHandler;

err=sigaction(SIGCHLD,&sa,NULL);//设置信号处理函数,该信号是子进程死亡的信号。

}

//我们直接看这个信号处理函数sigchldHandler。

static void sigchldHandler(int s)

{

pid_t pid;

int status;

while((pid=waitpid(-1,&status,WNOHANG))>0){

}else if(WIFSIGNALED(status)){

}

}

//如果死去的子进程是SS,则Zygote把自己也干掉了,这样就做到了生死与共!

if(pid==gDvm.systemServerPid){

kill(getpid(),SIGKILL);

}

}


OK,作为Zygote的嫡长子,SS确实具有非常高的地位,竟然到了与Zygote生死与共的地步!它为什么这么重要呢?我们现在就从forkSystemServer下手来分析SS究竟承担了怎样的工作使命。

注意 关于源代码定位的问题,不少人在面对浩瀚的代码时,常常不知道具体函数是在哪个文件中定义的。这里,就Source insight的使用提几点建议:

1)加入工程的时候,不要把所有目录全部加进去,否则会导致解析速度异常缓慢。我们可以先加入framework目录,在以后另有需要时,再加入其他目录。

2)除了Source insight的工具外,还需要有一个能搜索文件中特定字符串的工具,我用的是coolfind。我就是通过它在源码中搜索到forkSystemServer这个函数的,并且找到了它的实现文件dalvik_system_Zygote.c。在Linux下也有对应的工具,但其工作速度比coolfind缓慢。

3)在Linux下,可通过wine(一个支持Linux平台安装Windows软件的工具)安装Source insight。