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方法,下一节分析。