4.3.3 启动system_server进程

系统在预加载了共享资源后,便开始启动system_server进程,该进程是理解框架层的基础。Android中所有系统服务都由该进程启动,它的异常退出会直接导致zygote“自杀”,这样整个Java世界便会崩溃。

system_server的启动入口是startSystemServer,位于ZygoteInit.java中,代码如下:


private static boolean startSystemServer()

throws MethodAndArgsCaller, RuntimeException{

/启动system_server的命令行参数/

String args[]={

"—setuid=1000",//设置用户ID为1000,这个UID便代表系统权限

"—setgid=1000",

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

1009,1010,1018,3001,3002,3003,3006,3007",

"—capabilities=130104352,130104352",

"—runtime-init",

"—nice-name=system_server",//设置进程名

"com.android.server.SystemServer",//设置要启动的类名

};

ZygoteConnection.Arguments parsedArgs=null;

int pid;

try{

/将args数组分解成Arguments类型的对象,过程很简单/

parsedArgs=new ZygoteConnection.Arguments(args);

ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);

ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

/调用系统fork函数创建子进程,这个子进程就是system_server/

pid=Zygote.forkSystemServer(

parsedArgs.uid, parsedArgs.gid,

parsedArgs.gids,

parsedArgs.debugFlags,

null,

parsedArgs.permittedCapabilities,

parsedArgs.effectiveCapabilities);

}catch(IllegalArgumentException ex){

throw new RuntimeException(ex);

}

/pid为0说明在子进程system_server中/

if(pid==0){

/在子进程system_server中调用了handleSystemServerProcess方法/

handleSystemServerProcess(parsedArgs);

}

/在父进程中返回/

return true;

}


到这里zygote做了第一次分裂,fork出系统服务的总管system_server进程。这个过程分为以下两个重要的步骤:

1)通过forkSystemServer创建system_server子进程。

2)在子进程中调用handleSystemServerProcess方法。

1.通过forkSystemServer创建system_server子进程

启动system_server的第一步便是调用zygote的forkSystemServer方法,在该方法内部将调用Native方法nativeForkSystemServer完成启动system_server进程的任务。nativeForkSystemServer的JNI层实现方法位于dalvik/vm/native/dalvik_system_Zygote.cpp中,方法名为Dalvik_dalvik_system_Zygote_forkSystemServer,代码如下:


static void Dalvik_dalvik_system_Zygote_forkSystemServer(

const u4args, JValuepResult)

{

pid_t pid;

/间接调用了forkAndSpecializeCommon函数/

pid=forkAndSpecializeCommon(args, true);

if(pid>0){//system_server的父进程zygote中

int status;

gDvm.systemServerPid=pid;//在虚拟机中记录system_server的进程ID

/*退出前,重新检查system_server进程是否有异常。如果异常退出,则zygote

直接“自杀”。因为在zygote的服务项中配置了onrestart这个Option,所以

zygote“自杀”后,init进程会重新启动它*/

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

kill(getpid(),SIGKILL);

}

}

RETURN_INT(pid);

}


可见系统会检查system_server进程是否启动成功,如果启动失败,将导致zygote重启。system_server负责构建Native System Service和Java System Service,如果启动失败,整个Java世界也无从谈起,所以必须重启zygote。因此Dalvik_dalvik_system_Zygote_forkSystemServer方法的功能分成两部分:

1)启动system_server进程。

2)监控system_server进程的启动结果。

(1)启动system_server进程

这部分功能由forkAndSpecializeCommon函数实现,其位于dalvik_system_Zygote.cpp中,代码如下:


static pid_t forkAndSpecializeCommon(const u4*args, bool isSystemServer)

{

……//省略部分内容

/设置信号处理函数/

setSignalHandler();

/调用fork函数/

pid=fork();

if(pid==0){//子进程中

……//省略子进程中的常规处理代码

}else if(pid>0){

/父进程中/

}

return pid;

}


forkAndSpecializeCommon函数通过fork系统函数创建子进程system_server,并在创建system_server前做了重要工作:注册信号处理函数。该信号处理函数有什么作用呢?接下来setSignalHandler函数,代码如下:


static void setSignalHandler()

{

/*这里是非常通用的Linux注册信号处理函数的流程。调用系统函数sigaction处理SIGCHLD

信号,具体的处理函数是sigchldHandler。SIGCHLD信号是子进程退出信号/

int err;

struct sigaction sa;

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

sa.sa_handler=sigchldHandler;

err=sigaction(SIGCHLD,&sa, NULL);

if(err<0){

LOGW("Error setting SIGCHLD handler:%s",strerror(errno));

}

}


setSignalHandler注册了信号处理函数sigchldHandler,处理的信号便是SIGCHLD,代表子进程退出信号。

(2)监控system_server进程的启动结果

当子进程退出时,由sigchldHandler来处理该信号。接下来分析sigchldHandler是如何处理SIGCHLD信号的,代码如下:


static void sigchldHandler(int s)

{

pid_t pid;

int status;

/*调用系统函数waitpid等待子进程退出。第一个参数-1表示等待任何子进程。

*第二个参数status用于收集子进程退出时候的状态。

第三个参数WNOHANG表示如果没有子进程退出,不需要阻塞/

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

if(WIFEXITED(status)){

……//省略处理子进程退出时候的状态代码

}else if(WIFSIGNALED(status)){

……//省略处理子进程退出时候的状态代码

}

if(pid==gDvm.systemServerPid){

/*如果退出的是system_server进程,zygote又“自杀”了。SIGKILL

是“自杀”信号。虽然zgyote“自杀”了,但init进程会负责救活它的/

kill(getpid(),SIGKILL);

}

}

……//省略部分内容


从forkSystemServer函数的执行过程可以看出:zygote创建system_server进程是十分谨慎的,不但在创建之初判断system_server是否退出,而且在创建后还专门注册信号处理函数监控system_server的运行状态。如果system_server出现意外,zygote自己也就“羞愤自杀”了,这样会导致整个Java世界崩溃。

为什么system_server是如此重要,竟然关系到整个Java世界的生死存亡?接下来继续分析fork出system_server后都做了些什么。

2.在子进程中调用handleSystemServerProcess方法

system_server进程启动后,便开始调用handleSystemServerProcess方法,该方法位于ZygoteInit.java中,代码如下:


private static void handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs)

throws ZygoteInit.MethodAndArgsCaller{

closeServerSocket();//关闭fork时从zygote继承下来的Socket

/*set umask to 0077 so new files and directories

will default to owner-only permissions./

FileUtils.setUMask(FileUtils.S_IRWXG|FileUtils.S_IRWXO);

if(parsedArgs.niceName!=null){

Process.setArgV0(parsedArgs.niceName);

}

/根据invokeWith参数,执行一个Shell命令/

if(parsedArgs.invokeWith!=null){

WrapperInit.execApplication(parsedArgs.invokeWith,

parsedArgs.niceName, parsedArgs.targetSdkVersion,

null, parsedArgs.remainingArgs);

}else{

/调用zygoteInit方法,并传入参数/

RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,

parsedArgs.remainingArgs);

}/should never reach here/}


system_server生成后,迅速进入工作状态,执行handleSystemServerProcess。在该方法中,首先做了一些清理和初始化工作,接着调用RuntimeInit.zygoteInit方法。

RuntimeInit. zygoteInit方法的代码如下:


public static final void zygoteInit(int targetSdkVersion, String[]argv)

throws ZygoteInit.MethodAndArgsCaller{

redirectLogStreams();

commonInit();

nativeZygoteInit();

applicationInit(targetSdkVersion, argv);

}


zygoteInit封装了对四个方法的调用,对应四个步骤实现不同的初始化操作,下面详细分析这四步。

(1)redirectLogStreams方法重定向标准I/O操作

redirectLogStreams()方法重定向了Java的标准I/O操作到Android日志系统,代码如下:


public static void redirectLogStreams(){

System.out.close();

System.setOut(new AndroidPrintStream(Log.INFO,"System.out"));

System.err.close();

System.setErr(new AndroidPrintStream(Log.WARN,"System.err"));

}


这段代码非常简单,redirectLogStreams将Java的System.out调用重定向到Android标准的日志系统。

(2)commonInit方法初始化通用设置

commonInit方法做了一些通用的初始化操作,代码如下:


private static final void commonInit(){

//设置未捕获异常的默认处理函数

Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());

//获取persist.sys.timezone属性

TimezoneGetter.setInstance(new TimezoneGetter(){

@Override

public String getId(){

return SystemProperties.get("persist.sys.timezone");

}

});

TimeZone.setDefault(null);

//Android Iog配置

LogManager.getLogManager().reset();

new AndroidConfig();

//默认的HTTP User-Agent,用于HTTP连接

String userAgent=getDefaultUserAgent();

System.setProperty("http.agent",userAgent);

NetworkManagementSocketTagger.install();//网络相关

//模拟器上的trace调试

String trace=SystemProperties.get("ro.kernel.android.tracing");

if(trace.equals("1")){

Debug.enableEmulatorTraceOutput();

}

initialized=true;

}


(3)onZygoteInit方法开启Binder通信

nativeZygoteInit是一个Native方法,其JNI实现方法位于AndroidRuntime.cpp中,方法名为com_android_internal_os_RuntimeInit_nativeZygoteInit,代码如下:


static void com_android_internal_os_RuntimeInit_nativeZygoteInit(

JNIEnv*env, jobject clazz)

{

gCurRuntime->onZygoteInit();

}


gCurRuntime是在AndroidRuntime的构造函数中初始化为this的全局变量,这里调用了AndroidRuntime的onZygoteInit方法。onZygoteInit是个虚方法,运行时调用的是子类AppRuntime的onZygoteInit方法,因此直接分析AppRuntime的同名方法,代码如下:


virtual void onZygoteInit()

{

sp<ProcessState>proc=ProcessState:self();

/创建PoolThread对象,用于Binder通信/

proc->startThreadPool();

}


onZygoteInit开启了system_server的Binder通信通道,关于Binder的内容在第5章和第6章分析,目前只需要知道现在system_server可以使用Binder通信即可。

(4)invokeStaticMain方法抛出异常

applicationInit做了虚拟机设置并转化了参数后,便调用了invokeStaticMain方法。这里直接分析invokeStaticMain方法,代码如下:


private static void invokeStaticMain(String className, String[]argv)

throws ZygoteInit.MethodAndArgsCaller{

Class<?>cl;

/利用Java反射机制加载类信息,这里的className便是com.android.server.SystemServer,这个类名是在startSystemServer方法配置的参数中设置的*/

try{

cl=Class.forName(className);

}catch(ClassNotFoundException ex){

……//省略异常处理

}

Method m;

/利用Java反射机制,得到com.android.server.SystemServer类的main方法/

try{

m=cl.getMethod("main",new Class[]{String[].class});

}catch(NoSuchMethodException ex){

……//省略异常处理

}catch(SecurityException ex){

……//省略异常处理

}

/利用Java反射机制,判断main方法修饰符是否为static和public/

int modifiers=m.getModifiers();

if(!(Modifier.isStatic(modifiers)&&Modifier.isPublic(modifiers))){

throw new RuntimeException(

"Main method is not public and static on"+className);

}

/抛出异常/

throw new ZygoteInit.MethodAndArgsCaller(m, argv);

}


invokeStaticMain方法加载了com.android.server.SystemServer类信息,然后便抛出一个MethodAndArgsCaller类型的异常,就“罢工”了。这是怎么回事?既然抛出了异常,那一定有捕获异常的地方,否则进程就退出了。异常捕获的部分位于ZygoteInit开启Java世界的第四步,即执行MethodAndArgsCaller的run方法,下一节分析。