Zygote如何启动SystemServer进程?

前言

在上一篇文章中,我们知道了Zygote进程负责启动Systemserver进程的。在这篇文章中,我们具体讲讲Zygote启动SystemServer进程时,经历了什么?

SystemServer主要是用来创建各种系统服务的,像AMS、PMS、WMS等常见的系统服务,都是在SystemServer进程里创建的,它们并没有属于自己的一个进程。

时序图

还是先来看看时序图吧:
在的插入图片描述

源码流程

1、main()

在ZygoteInit.java文件里,main()方法里调用了startSystemServer()方法,就是来启动SystemServer进程的,源码如下:

//代码文件位置:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
 
     *****省略部分代码*****
    if (startSystemServer) {
        //注意,在这里启动了SystemServer进程
        startSystemServer(abiList, socketName, zygoteServer);
    }
    Log.i(TAG, "Accepting command socket connections");
    //一直循环,等待AMS的请求,去fork子进程
    zygoteServer.runSelectLoop(abiList);
}

2、startSystemServer()

再来看看startSystemServer()方法里面做了什么:

//代码文件位置:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
 private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
            throws Zygote.MethodAndArgsCaller, RuntimeException {
 
     *****省略部分代码*****
     //当前运行在SystemServer进程中
    if (pid == 0) {
    	if (hasSecondZygote(abiList)) {
        	waitForSecondaryZygote(socketName);
        }
        //关闭Zygote进程创建的Socket,因为用不到
        zygoteServer.closeServerSocket();
        handleSystemServerProcess(parsedArgs);
    }
       return true;
}

SystemServer进程复制了Zygote进程的地址空间,所以也会得到Zygote进程创建的Socket,但SystemServer用不到,所以调用了zygoteServer.closeServerSocket()关闭了Socket。

3、handleSystemServerProcess()

我们接着来看看handleSystemServerProcess(parsedArgs);的源码:

//代码文件位置:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
 private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws Zygote.MethodAndArgsCaller {
 
     *****省略部分代码*****
    if (parsedArgs.invokeWith != null) {
    	*****省略部分代码*****
    }else{
    	ClassLoader cl = null;
        if (systemServerClasspath != null) {
        	cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);
                Thread.currentThread().setContextClassLoader(cl);
            }
            ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
    }
}

首先通过createPathClassLoader()创建了一个PathClassLoader,接着继续调用zygoteInit()。

4、zygoteInit()

我们继续看源码:

//代码文件位置:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
 public static final void zygoteInit(int targetSdkVersion, String[] argv,
            ClassLoader classLoader) throws Zygote.MethodAndArgsCaller {
 
     if (RuntimeInit.DEBUG) {
            Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
        }

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
        RuntimeInit.redirectLogStreams();

        RuntimeInit.commonInit();
        //启动Binder线程池
        ZygoteInit.nativeZygoteInit();
        //进入SystemServer的main()方法
        RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}

首先调用nativeZygoteInit方法,一看方法的名字就知道调用了Native层的代码,是用来启动Binder线程池的(Binder通信用的),启动完Binder线程池后,再调用RuntimeInit.applicationInit()方法,就进入SystemServer的main方法。

这里我们先来研究下,如何启动Binder线程池的。

4-1 启动Binder线程池

nativeZygoteInit是一个Native方法,所以我们得去找它对应的JNI文件,如下:

//代码文件位置:frameworks/base/core/jni/AndroidRuntime.cpp
 int register_com_android_internal_os_ZygoteInit(JNIEnv* env)
{
    const JNINativeMethod methods[] = {
        { "nativeZygoteInit", "()V",
            (void*) com_android_internal_os_ZygoteInit_nativeZygoteInit },
    };
    return jniRegisterNativeMethods(env, "com/android/internal/os/ZygoteInit",
        methods, NELEM(methods));
}
}

通过JNI的数组JNINativeMethod methods[] ,可以知道nativeZygoteInit方法对应的JNI文件是AndroidRuntime.cpp的com_android_internal_os_ZygoteInit_nativeZygoteInit函数:

//代码文件位置:frameworks/base/core/jni/AndroidRuntime.cpp
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}

这里的gCurRuntime是AndroidRuntime类型的指针,具体指向的是AndroidRuntime的子类AppRuntime,它在app_main.cpp里定义。所以我们接着来看AppRuntime的onZygoteInit方法:

//代码文件位置:frameworks/base/cmds/app_process/app_main.cpp
 virtual void onZygoteInit()
    {
        sp<ProcessState> proc = ProcessState::self();
        ALOGV("App process: starting thread pool.\n");
        proc->startThreadPool();
    }

可以看到 proc->startThreadPool();就是用来启动一个Binder线程池的,这样SystemServer进程就可以使用Binder来与其他进程进行通信了。

4-2 进入SystemServer的main方法

前面我们知道了在ZygoteInit.java里的zygoteInit()方法中,先是调用ZygoteInit.nativeZygoteInit();来开启Binder线程池,接着调用RuntimeInit.applicationInit(),进入SystemServer的main方法:

//代码文件位置:frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
 protected static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws Zygote.MethodAndArgsCaller {
    
    	*****省略部分代码*****
       	invokeStaticMain(args.startClass, args.startArgs, classLoader);
    }

在applicationInit()方法中,主要调用了invokeStaticMain()方法:

//代码文件位置:frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
  private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
            throws Zygote.MethodAndArgsCaller {
    
    	try {
    		//通过反射得到SystemServer类
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }

        Method m;
        try {
        	//接着,找到SystemServer的main()方法
            m = cl.getMethod("main", new Class[] { String[].class });
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException(
                    "Missing static main on " + className, ex);
        } catch (SecurityException ex) {
            throw new RuntimeException(
                    "Problem getting static main on " + className, ex);
        }

        int modifiers = m.getModifiers();
        if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
            throw new RuntimeException(
                    "Main method is not public and static on " + className);
        }
        //最后把main方法跟着抛出去
        throw new Zygote.MethodAndArgsCaller(m, argv);
    }

这里面的className,就是外部一路传进来的"com.android.server.SystemServer"。
先是通过反射拿到cl也就是SystemServer类,接着找到SystemServer的main方法,再接着把main方法传入MethodAndArgsCaller异常中并抛出这个异常,在外部的ZygoteInit.java的main方法中,会捕获这个异常,捕获后会调用SystemServer.main方法:

//代码文件位置:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
 public static void main(String argv[]) {
    
    	*****省略部分代码*****
       	    zygoteServer.closeServerSocket();
        } catch (Zygote.MethodAndArgsCaller caller) {
            caller.run();
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            zygoteServer.closeServerSocket();
            throw ex;
        }
    }

当捕获到Zygote.MethodAndArgsCaller 时,会去调用caller.run(),这个caller还是Zygote.MethodAndArgsCaller 类型:

//代码文件位置:frameworks/base/core/java/com/android/internal/os/Zygote.java
 public static class MethodAndArgsCaller extends Exception
            implements Runnable {
    
        private final Method mMethod;
        private final String[] mArgs;
        public MethodAndArgsCaller(Method method, String[] args) {
            mMethod = method;
            mArgs = args;
        }

        public void run() {
			try {
				//调用了SystemServer的main方法
                mMethod.invoke(null, new Object[] { mArgs });
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InvocationTargetException ex) {
                Throwable cause = ex.getCause();
                if (cause instanceof RuntimeException) {
                    throw (RuntimeException) cause;
                } else if (cause instanceof Error) {
                    throw (Error) cause;
                }
                throw new RuntimeException(ex);
            }
		}
    }

到此,就进入了SystemServer的main方法了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值