Android 进阶——系统启动之核心SystemServer进程启动详解

Posted CrazyMo_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 进阶——系统启动之核心SystemServer进程启动详解相关的知识,希望对你有一定的参考价值。

引言

对了如果我的文章对你有些许帮助,或许你可以花几秒钟动动手指投个票,感激,直通车五星好评,加油共勉!

前面系列文章介绍了android系统的第一个用户进程——init进程由解析init.rc脚本启动,完成属性系统的初始化等工作后紧接着启动Android系统上的造物者——Zygote进程在Zygote 进程启动过程中会把Android 最核心进程SystemServer进程创建并启动。

基于Android 26,方法在本系列文章代表Java层,函数指Native层的,仅供参考。

以后更多精选系列文章以高度完整的系列形式发布在公众号,真正的形成一套完整的技术栈,欢迎关注,目前第一个系列是关于Android系统启动系列的文章,大概有二十几篇干货:

一、SystemServer 进程概述

SystemServer进程(System进程,名为system_server)在Android 系统中运行着各种系统核心服务ActivityManagerService、PackageManagerService、ContentService、WindowManagerService等六十多种服务,为了保护Android系统,Android 应用没有权限直接访问设备的底层资源,都是通过Binder去调用SystemService中的服务代理对象。在Zygote 进程启动后,由Zygote fork自身创建SystemServer进程并马上启动执行SystemServer类的main方法。

由于System进程是由Zygote fork自身而得到的,就是说System进程复制了Zygote进程的地址空间,也同样在启动时创建了一个socket。

二、SystemServer进程的创建

整体上可以把SystemServer进程创建分为两个阶段:首先是Zygote 进程fork 创建初始化SystemServer进程,然后是返回到SystemServer进程中执行SystemServer#main方法初始化和启动各种系统服务

/frameworks/base/cmds/app_process/app_main.cpp # main 解析init.rc 脚本传入的参数,触发AppRuntime #start函数进而执行ZygoteInit#main 方法。

1、ZygoteInit.main方法里调用startSystemServer方法触发SystemServer 进程的创建

前面分析得知在init.rc脚本中定义的Zygote进程的启动参数中包括了--start-system-server等,因此Zygote 进程会在ZygoteInit.main方法里调用startSystemServer方法来 fork 出SystemServer进程,startSystemServer 方法主要是做了三件事:

  1. 为SystemServer 准备启动参数(包括制定uid和gid为1000,执行Java类为com.android.SystemServer等)
  2. 通过调用Zygote.forkSystemServer方法真正fork 出SystemServer进程(JNI调用nativeForkSystemServer函数)
  3. fork 创建SystemServer进程后,返回到SystemServer进程中,真正开始初始化SystemServer(执行ZygoteInit.java #handleSystemServerProcess(parsedArgs)方法)。
private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException 

        /* Hardcoded command line to start the system server */
        //System进程启动的参数,可以看到System进程的用户ID和用户组ID都是1000,同时还有其他用户组的权限
        String args[] = 
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007,3009,3010",
            "--capabilities=" + capabilities + "," + capabilities,
            "--nice-name=system_server",
            "--runtime-args",
            "com.android.server.SystemServer",
        ;
        ZygoteConnection.Arguments parsedArgs = null;
        int pid;
        try 
            parsedArgs = new ZygoteConnection.Arguments(args);
            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
            /* Request to fork the system server process */
            //fork 创建System进程
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        
        /* For child process  fork 后返回到SystemServer进程*/
        if (pid == 0) 
            if (hasSecondZygote(abiList)) 
                if(isBox)
                    waitForSecondaryZygote(socketName);
                
                Log.d(TAG,"--------call waitForSecondaryZygote,skip this---,abiList= "+abiList);
            
            // 处理System进程启动事宜
            handleSystemServerProcess(parsedArgs);
        
        return true;
    

2、Zygote.forkSystemServer 方法触发fork 创建SystemServer进程

应用启动时会调用Zygote 类的forkAndSpecialize 方法来fork出子进程,而SystemServer进程是由forkSystemServer方法 fork出来的,虽然本质都是通过JNI 调用\\frameworks\\base\\core\\jni\\com_android_internal_os_Zygote.cpp中native函数完成

static jint com_android_internal_os_Zygote_nativeForkSystemServer(
        JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
        jint debug_flags, jobjectArray rlimits, jlong permittedCapabilities,
        jlong effectiveCapabilities) 
    //真正去调用系统调用fork 创建
  pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
                                      debug_flags, rlimits,
                                      permittedCapabilities, effectiveCapabilities,
                                      MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL,
                                      NULL, NULL);
  if (pid > 0) 
      ALOGI("System server process %d has been created", pid);
      gSystemServerPid = pid;
      int status;
      //Zygote进程中检查SystemServer 是否启动成功
      if (waitpid(pid, &status, WNOHANG) == pid) 
          ALOGE("System server process %d has died. Restarting Zygote!", pid);
          RuntimeAbort(env, __LINE__, "System server process has died. Restarting Zygote!");
      
  
  return pid;


当native层执行完毕ForkAndSpecializeCommon函数后,还会返回Zygote进程中检查SystemServer 是否启动成功,如果SystemServer 启动不成功,系统会从Zygote开始再启动一遍。

static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
                                     jint debug_flags, jobjectArray javaRlimits,
                                     jlong permittedCapabilities, jlong effectiveCapabilities,jint mount_external,jstring java_se_info, jstring java_se_name,bool is_system_server, jintArray fdsToClose,jstring instructionSet, jstring dataDir) 
  SetSigChldHandler();
	...
  pid_t pid = fork();
	...
  if (pid == 0) 
    rc = selinux_android_setcontext(uid, is_system_server, se_info_c_str, se_name_c_str);
	...
    if (se_info_c_str == NULL && is_system_server) 
      se_name_c_str = "system_server";
    
    if (se_info_c_str != NULL) 
      SetThreadName(se_name_c_str);
    
    UnsetSigChldHandler();
    env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags,
                              is_system_server, instructionSet);
							  ...
  
  return pid;


从代码中可以看到在fork之前,首先注册了SIGCHILD信号的处理函数SIGChildHandler 函数,当捕捉到这个SIGCHILD信号(通常是子进程死亡时)后,除了调用waitpid来防止子进程变“僵尸”外,还会再判断是否是SystemServer进程,如果是,Zygote进程会自杀,进而导致Init进程杀死所有用户进程并重启Zygote。

三、SystemServer 进程的初始化

1、返回ZygoteInit#handleSystemServerProcess方法SystemServer开始初始化工作

\\frameworks\\base\\core\\java\\com\\android\\internal\\os\\ZygoteInit.java

当Zygote进程在main方法里fork出SystemServer进程后,回到ZygoteInit.main方法中继续往下执行ZygoteInit#handleSystemServerProcess方法开始初始化SystemServer进程,首先将SystemServer进程的umask设为0077,这样当SystemServer 创建的文件的属性就是0077,即只有SystemServer 进程才可以访问,然后把SystemServer进程的名称修改为system_server

    /**
     * Finish remaining work for the newly forked system server process.
     */
    private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller 
		    // set umask to 0077 so new files and directories will default to owner-only permissions.
        Os.umask(S_IRWXG | S_IRWXO);
        if (parsedArgs.niceName != null) 
            Process.setArgV0(parsedArgs.niceName);
        
        	...
        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
        if (systemServerClasspath != null) 
            performSystemServerDexOpt(systemServerClasspath);
        

        if (parsedArgs.invokeWith != null) 
            ...
         else 
            ClassLoader cl = null;
            if (systemServerClasspath != null) 
                cl = createPathClassLoader(systemServerClasspath, parsedArgs.targetSdkVersion);

                Thread.currentThread().setContextClassLoader(cl);
            
            /*
             * Pass the remaining arguments to SystemServer.
             */
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
        
    

首次执行时parsedArgs.invokeWith 为null,所以首先是执行 ZygoteInit.zygoteInit方法来反射调用SystemServer类的main方法。

2、执行/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java # zygoteInit 方法继续初始化System进程

在返回到System进程后最终执行 RuntimeInit.java # zygoteInit 方法继续启动System进程:

  • commonInit 方法配置System进程的时区、键盘布局等通用信息

  • nativeZygoteInit 方法在System进程中开启一个Binder线程池

  • 执行invokeStaticMain方法,表示要触发类名为“"com.android.server.SystemServer”静态成员main方法,即作为System进程的”入口“

    在ZygoteInit.java # startSystemServer 中fork System 进程时传递的类名为"com.android.server.SystemServer“

    /**
     * The main function called when started through the zygote process. This
     * could be unified with main(), if the native code in nativeFinishInit()
     * were rationalized with Zygote startup.<p>
     * @param targetSdkVersion target SDK version
     * @param argv arg strings argv 最后一个参数的值为"com.android.server.SystemServer"
     */
    public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller 
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
        redirectLogStreams();

        commonInit();
        nativeZygoteInit();
        //invokeStaticMain 在这里被执行
        applicationInit(targetSdkVersion, argv, classLoader);
    

实际上System进程进入到com.android.server.SystemServer # main方法时,已经执行了很多代码量,从严格意义上讲main方法并不是System进程的入口方法,只不过Runtime#invokeStaticMain 使用了巧妙地方法来调用它使之变成是System进程的入口。

3、执行 /frameworks/base/services/java/com/android/server/SystemServer.java # main方法完成SystemServer的初始化

在SystemServer.java # main方法里完成系统属性的初始化、核心系统服务的启动、Handler 消息机制的初始化以及其他重要系统服务的启动。

    /**
     * The main entry point from zygote.
     */
    public static void main(String[] args) 
        new SystemServer().run();
    
    private void run() 
        try 
            if (!SystemProperties.get("persist.sys.language").isEmpty()) 
                final String languageTag = Locale.getDefault().toLanguageTag();
                SystemProperties.set("persist.sys.locale", languageTag);
                SystemProperties.set("persist.sys.language", "");
                SystemProperties.set("persist.sys.country", "");
                SystemProperties.set("persist.sys.localevar", "");
            
    			...
            // Here we go!
            Slog.i(TAG, "Entered the Android system server!");
            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis());
            //设置当前的虚拟机的运行库路径
            SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
            // Mmmmmm... more memory!
            VMRuntime.getRuntime().clearGrowthLimit();

            // The system server has to run all of the time, so it needs to be
            // as efficient as possible with its memory usage.
            VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);    
            // Increase the number of binder threads in system_server
            BinderInternal.setMaxThreads(sMaxBinderThreads);

            // Prepare the main looper thread (this thread).
            android.os.Process.setThreadPriority(
                android.os.Process.THREAD_PRIORITY_FOREGROUND);
            android.os.Process.setCanSelfBackground(false);
            Looper.prepareMainLooper();

            // Initialize native services.
            System.loadLibrary("android_servers");

            // Check whether we failed to shut down last time we tried.
            // This call may not return.
            performPendingShutdown();

            // Initialize the system context.
            createSystemContext();
                      
            // Create the system service manager.
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
         finally 
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        

        // Start services.
        try 
            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
         catch (Throwable ex) 
            throw ex;
         finally 
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        
    

3.1、 System.loadLibrary(“android_servers”) 加载framework/base/services/jni下的libandroid_servers.so库并初始化相关native服务

3.2、 createSystemContext() 获取系统的Context并设置主题

通过ActivityThread的systemMain方法来获取ActivityThread对象进而获取系统的Context,最终设置系统主题

    private void createSystemContext() 
        ActivityThread activityThread = ActivityThread.systemMain();
        mSystemContext = activityThread.getSystemContext();
        mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
        final Context systemUiContext = activityThread.getSystemUiContext();
        systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
    

3.2.1、在ActivityThread.systemMain方法中创建ActivityThread对象并调用ActivityThread#attach方法

    public static ActivityThread systemMain() 
        ...
        ActivityThread thread = new ActivityThread();
        thread.attach(true);
        return thread;
    

3.2.2、在ActivityThread.attach方法中创建Instrumentation对象和Context(ContextImpl)对象

   private void attach(boolean system) 
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) 
        	...
         else 
            try 
                mInstrumentation = new Instrumentation();
                ContextImpl context = ContextImpl.createAppContext(this, getSystemContext().mPackageInfo);
                mInitialApplication = context.mPackageInfo.makeApplication(true, null);
                mInitialApplication.onCreate();
             catch (Exception e) 
                throw new RuntimeException(
                        "Unable to instantiate Application():" + e.toString(), e);
            
        
        ...
        ViewRootImpl.addConfigCallback(configChangedCallback);
    

attach时传入的system参数值为true时,会创建一个类似应用的环境,创建了ContextImpl、Application对象并调用Application#onCreate方法,完全是在创建一个应用。每一个上下文对象都需要对应一个APK文件,注意查看ContextImpl里的PackgeInfo对象(来源于ActivityThread#getSystemContext方法)

每一个上下文对象都需要对应一个APK文件,换言之每一个Context对象对应着一个APP的环境,同时每个App 也对应着一个Application对象

    public ContextImpl getSystemContext() 
        synchronized (this) 
            if (mSystemContext == null) 
                mSystemContext = ContextImpl.createSystemContext(this);
            
            return mSystemContext;
        
    

当mSystemContext为null时,会调用ContextImpl.createSystemContext方法中创建。

3.2.3、在ContextImpl.createSystemContext方法中创建LoadedApk对象

    static ContextImpl createSystemContext(ActivityThread mainThread) 
        LoadedApk packageInfo = new LoadedApk(mainThread);
        ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, 0,
                null);
        context.setResources(packageInfo.getResources());
        context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
                context.mResourcesManager.getDisplayMetrics());
        return context;
    

而LoadedApk 构造方法

/**
     * Create information about the system package.
     * Must call @link #installSystemApplicationInfo later.
     */    
LoadedApk(ActivityThread activityThread) 
        mActivityThread = activityThread;
        mApplicationInfo = new ApplicationInfo();
        mApplicationInfo.packageName = "android";
        mPackageName = "android";
        ...
        mClassLoader = ClassLoader.getSystemClassLoader();
        mResources = Resources.getSystem();
    

可以看到包名为android(framework-res.apk的包名也是android),自然getSystemContext方法放回的mSystemContext 所对应的apk文件其实是framework-res.apk,当attach方法被执行时,新建的ContextImpl对象本质上是在复制mSystemContext,最终创建的Application对象相当于是framework-res.apk。总而言之,Activity#systemMain方法相当于创建了一个framework-res.apk 的上下文环境。

3.3、创建SystemServiceManager对象(管理系统服务)

3.4、startBootstrapServices、startCoreServices、startOtherServices启动所有系统服务

至于具体系统服务的启动系列留到后续文章一一详细分析,需要注意的是除了初始化系统服务之外,SystemServer还需要监控各种系统服务是否正常工作,因此设计了一套软件“看门狗方案”并在startOtherServices方法里创建并启动,至此SystemServer进程启动完毕,SystemServer进程在初始化的时候也需要和普通应用进程一样,创建一个类似应用的环境。

以上是关于Android 进阶——系统启动之核心SystemServer进程启动详解的主要内容,如果未能解决你的问题,请参考以下文章

Android 进阶——系统启动之Framework 核心ActivitityManagerService服务启动

Android 进阶——系统启动之Framework 核心ActivitityManagerService服务启动

Android 进阶——系统启动之Framework 核心ActivitityManagerService服务启动

Android 进阶——系统启动之核心SystemServer进程启动详解

Android 进阶——系统启动之Android init进程解析init.rc脚本

Android 进阶——系统启动之Android init进程解析init.rc脚本