【Android面试题】Android Framework核心面试题——SystemServer进程的启动流程

SystemServer进程的启动流程

这道题想考察什么?

这道题想考察同学对SystemServer进程的了解。

考生应该如何回答

SystemServer进程是由zygote进程启动的,它作为zygote进程的大儿子,它被赋予了重要的职责,启动并管理app运行所需要的绝大多数服务,其中包含:AMS ,ATMS,WMS,PKMS,PMS等等大概有90多个服务,这些服务的启动和管理流程的细节请看后面的分析。

1.SystemServer是做什么的

SystemServer进程主要是用于创建和管理系统服务的,例如AMS、WMS、PMS。由于SystemServer进程和应用进程由Zygote进程启动,所以接下来分析Zygote如何处理的SystemServer进程。

2.Zygote处理SystemServer进程

继上一题《Zygote进程的启动流程》的代码,在zygote#main() 函数中通过调用forkSystemServer()函数 fork SystemServer 进程,那么我们看一下下面的代码:

// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
private static Runnable forkSystemServer(String abiList, String socketName,
            ZygoteServer zygoteServer) {
        try {
            // 1.创建SystemServer进程,并返回当前进程的pid
            pid = Zygote.forkSystemServer(
                    parsedArgs.mUid, parsedArgs.mGid,
                    parsedArgs.mGids,
                    parsedArgs.mRuntimeFlags,
                    null,
                    parsedArgs.mPermittedCapabilities,
                    parsedArgs.mEffectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        // 2.如果pid==0则说明Zygote进程创建SystemServer进程成功,当前运行在SystemServer进程中
        if (pid == 0) {
            // 3.由于SystemServer进程fork了Zygote进程的地址空间,所以会得到Zygote进程创建的Socket,
            // 而这个Socket对于SystemServer进程是无用的,因此,在此处关闭了该Socket。
            zygoteServer.closeServerSocket();
            // 4.启动SystemServer进程
            return handleSystemServerProcess(parsedArgs);
        }
    }

上面的代码执行过程会涉及到进程的fork,在代码1 处,Zygote.forkSystemServer()执行的过程中会创建一个进程,这个进程就是systemServer进程。那么fork完成后,此处的代码会返回两次,因为fork 会返回两次,一次返回是执行fork新创建的代码,另外一次是zygote自己的代码。第一次返回值如果是0 ,说明当前运行的是新的创建的进程的代码也就是systemServer进程的代码,第二次返回的值是一个大于0的值,说明当前运行的代码是zygote进程的代码。因此就有了后面的if判断也就是代码2处,如果 pid 等于0 ,说明当前进程是运行在systemServer进程中。systemServer进程是不需要zygoteServer的,于是就有了 closeServerSocket代码的存在。然后,再执行handleSystemServerProcess,运行systemServer进程。

private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
        if (parsedArgs.mInvokeWith != null) {
            ...
        } else {
            ClassLoader cl = null;
            if (systemServerClasspath != null) {
                // 1.使用了systemServerClassPath和targetSdkVersion创建了一个PathClassLoader
                cl = createPathClassLoader(systemServerClasspath, parsedArgs.mTargetSdkVersion);
            }

            // 2.调用 ZygoteInit.zygoteInit 方法
            return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                    parsedArgs.mDisabledCompatChanges,
                    parsedArgs.mRemainingArgs, cl);
        }
    }

以上代码做了两件事:1)基于sdk版本创建了一个ClassLoader;2)执行zygoteInit方法。

public static final Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {
        // 1.进入native方法
        ZygoteInit.nativeZygoteInit();
        // 2.获取封装了SystemServer的main函数的runnable
        return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
                classLoader);
    }

在zygoteInit函数中,首先是调用nativeZygoteinit函数来初始化进程环境,然后再执行applicationInit函数获取封装了SystemServer的main函数的Runnable。

2-1.ZygoteInit.nativeZygoteInit

在上一题《zygote进程的启动流程》中我们知道有一个流程,那就是在zygote初始化的时候会注册JNI,其中就有将nativeZygoteInit()方法和native函数com_android_internal_os_ZygoteInit_nativeZygoteInit()建立了映射关系。所以此时调用nativeZygoteInit()会调用到AndroidRuntime的下面的代码。

static AndroidRuntime* gCurRuntime = NULL;

static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}

gCurRuntime是AndroidRuntime的指针,具体指向的是其子类AppRuntime,它在app_main.cpp中定义。代码如下:

// frameworks/base/cmds/app_process/app_main.cpp
virtual void onZygoteInit()
    {
        // 1.创建了一个ProcessState实例
        sp<ProcessState> proc = ProcessState::self();
        // 2.启动了一个Binder线程池
        proc->startThreadPool();
    }

在这个代码中执行的是进程的初始化,首先在代码1处,创建了一个进程ProcessState,其中就会创建一个binder;然后在代码2处启动了Binder线程池,为Binder线程的运行提供了动力。

到目前为止SystemServer进程已经创建完成,那么接下来就需要运行systemServer进程了,所以我们回到RuntimeInit.applicationInit函数中进行分析。

2-2.RuntimeInit.applicationInit
// frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {
        return findStaticMain(args.startClass, args.startArgs, classLoader);
}
protected static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        Class<?> cl;
        try {
            // 1.通过反射得到了SystemServer类
            cl = Class.forName(className, true, classLoader);
        }

        Method m;
        try {
            // 2.找到了 SystemServer中的main方法
            m = cl.getMethod("main", new Class[] { String[].class });
        }

        // 3.将main()方法传入MethodAndArgsCaller()方法中
        return new MethodAndArgsCaller(m, argv);
    }

以上代码就是运用反射,拿到systemServer的main 函数,并且调用MethodAndArgsCaller,将main函数的调用封装到一个Runnable中,方便后期的执行。

static class MethodAndArgsCaller implements Runnable {
        private final Method mMethod;
        public MethodAndArgsCaller(Method method, String[] args) {
            mMethod = method;
            mArgs = args;
        }

        public void run() {
            try {
                // 执行SystemServer的main()方法
                mMethod.invoke(null, new Object[] { mArgs });
            }
        }
    }

这个Runnable的run方法是在ZygoteInit的main()方法中被执行。代码如下:

// frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
    try {
            if (startSystemServer) {
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
                if (r != null) {
                    r.run();  //1 执行run
                    return;
                }
            }
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            throw ex;
        } finally {
            if (zygoteServer != null) {
                zygoteServer.closeServerSocket();
            }
        }

如上面代码1处,执行run方法,这个时候就是执行方法main(),所以,接下来我们看systemServer main函数的执行。

3. SystemServer进程执行
// frameworks/base/services/java/com/android/server/SystemServer.java
public static void main(String[] args) {
        new SystemServer().run();
}

main函数就一行代码执行SystemServer进程的润函数:

private void run() {
        try {
            Looper.prepareMainLooper();

            // 1.加载动态库libandroid_servers.so
            System.loadLibrary("android_servers");

            // 2.创建SystemServerManager
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            
            // 3.初始化系统上下文
            createSystemContext();

        }

        try {
            // 3.使用SystemServiceManager启动引导服务
            startBootstrapServices(t);
            // 4.启动核心服务
            startCoreServices(t);
            // 5.启动其他服务
            startOtherServices(t);
        }

        // Loop forever.
        Looper.loop();
}

通过上面的代码不难发现,启动过程中,在大流程上systemServer和app进程的启动很像,初始化了很多资源,也加载了很多资源,还创建了上下文,同时构建了进程的Looper 死循环确保进程不会退出。当然,在SystemServer中最重要的内容还是通过代码3,4,5启动了非常多的服务,大概有90多个服务,这些服务包括AMS,ATMS,WMS,PKMS,BMS等等一系列的服务。另外,在代码2处创建了一个systemServiceManager对象,这个对象是用于在SystemServer进程中管理90多个服务的启动的。

4.总结

SystemService进程被创建后,主要的处理如下:

  1. 启动Binder线程池,这样就可以与其他进程进行Binder跨进程通信。
  2. SystemServer在启动过程中,先初始化一些系统变量,加载类库,创建Context对象。
  3. 创建SystemServiceManager,它用来对系统服务进行创建、启动和生命周期管理。
  4. 启动各种系统服务:引导服务、核心服务、其他服务,共90多种。应用开发主要关注引导服务ActivityManagerService、PackageManagerService和其他服务WindowManagerService、InputManagerService即可。
  5. SystemServer在启动服务前,会尝试与Zygote建立Socket通信,通信成功后才去启动服务。
  6. 启动的服务都单独运行在SystemServer的各自线程中,同属于SystemServer进程

最后

我整理了一套Android面试题合集,除了以上面试题,还包含【Java 基础、集合、多线程、虚拟机、反射、泛型、并发编程、Android四大组件、异步任务和消息机制、UI绘制、性能调优、SDN、第三方框架、设计模式、Kotlin、计算机网络、系统启动流程、Dart、Flutter、算法和数据结构、NDK、H.264、H.265.音频编解码、FFmpeg、OpenMax、OpenCV、OpenGL ES
在这里插入图片描述

有需要的朋友可以扫描下方二维码,免费领取全部面试题+答案解析!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值