🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
我们先回顾一下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); intdebugFlags = 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 voidDalvik_dalvik_system_Zygote_forkSystemServer( const u4* args, JValue* pResult) { pid_tpid; //根据参数,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_tpid; uid_tuid = (uid_t) args[0]; gid_tgid = (gid_t) args[1]; ArrayObject* gids = (ArrayObject *)args[2]; u4debugFlags = args[3]; ArrayObject *rlimits = (ArrayObject *)args[4]; //设置信号处理,待会儿要看看这个函数。 setSignalHandler(); pid =fork(); //fork子进程 if (pid== 0) { //对子进程要根据传入的参数做一些处理,例如设置进程名,设置各种id(用户id,组id等) } ...... } ~~~ 最后看看setSignalHandler函数,它由Zygote在fork子进程前调用,代码如下所示: **dalvik_system_Zygote.c** ~~~ static void setSignalHandler() { interr; structsigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = sigchldHandler; err =sigaction (SIGCHLD, &sa, NULL);//设置信号处理函数,该信号是子进程死亡的信号 } //我们直接看这个信号处理函数sigchldHandler static void sigchldHandler(int s) { pid_tpid; intstatus; 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)除了Sourceinsight的工具外,还需要有一个能搜索文件中特定字符串的工具,我用的是coolfind。forkSystemServer这个函数,就是通过它在源码中搜索到的,并且找到了实现文件dalvik_system_Zygote.c。在Linux下也有对应工具,但工作速度比coolfind缓慢。 - 3) 在Linux下,可通过wine(一个支持Linux平台安装Windows软件的工具)安装Source insight。