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。