Android源码学习--SystemServer进程

作者: PrivateGO | 来源:发表于2017-02-13 00:06 被阅读447次

    SystemServer进程在Android中的角色
    SystemServer进程是Android系统的核心之一,大部分Android提供的服务都运行在这个进程里,如AMS,PMS,等六十多种服务。我们都知道Android的应用进程没有权限直接访问设备的底层资源,只能通过SystemServer中的服务代理访问,这样做的目的是为了防止应用进程对系统造成破坏。

    SystemServer进程的创建过程

    一、 创建SystemServer进程
    ZygoteInit类的main()方法里调用startSystemServer()方法来启动SystemServer。

    //位于ZygoteInit.java
    private static boolean startSystemServer(String abiList, String socketName)
                throws MethodAndArgsCaller, RuntimeException {
            ...
            // 准备启动参数
            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 {
                ...
                pid = Zygote.forkSystemServer(
                        parsedArgs.uid, parsedArgs.gid,
                        parsedArgs.gids,
                        parsedArgs.debugFlags,
                        null,
                        parsedArgs.permittedCapabilities,
                        parsedArgs.effectiveCapabilities);
            } catch (IllegalArgumentException ex) {
                throw new RuntimeException(ex);
            }
            // 进入子进程system_server
            if (pid == 0) {
                if (hasSecondZygote(abiList)) {
                    waitForSecondaryZygote(socketName);
                }
                // 完成system_server进程剩余的工作
                handleSystemServerProcess(parsedArgs);
            }
            return true;
        }
    

    在startSystemServer()方法中,主要做了3件事:
    1.为SystemServer准备启动参数。
    SystemServer进程的uid和gid都被指定为1000。SystemServer进程的名字是system_server,其执行类是com.android.server.SystemServer。
    2.调用Zygote类的forkSystemServer()来fork出SystemServer子进程。
    forkSystemServer()方法最终会调用native层的nativeForkSystemServer()函数,最终调用ForkAndSpecializeCommon函数来执行实际的fork操作。
    在native层调用完forkAndSpecializeCommon()函数后,如果启动的是SystemServer,Zygote会检查SystemServer是否启动成功,如果失败,Zygote进程会让进程自己退出,重启zygote进程。

    //位于com_android_internal_os_Zygote.cpp
    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) {
          // zygote进程检测子进程是否创建
          gSystemServerPid = pid;
          int status;
          if (waitpid(pid, &status, WNOHANG) == pid) {
              // system_server进程死亡后,重启zygote进程
              RuntimeAbort(env, __LINE__, "System server process has died. Restarting Zygote!");
          }
      }
      return pid;
    }
    

    在ForkAndSpecializeCommon()函数中将调用fork()函数来创建子进程之前还调用了SetSigChldHandler函数设置处理SIGCHLD信号的函数SigChldHandler()。

    static void SigChldHandler(int /*signal_number*/) {
      pid_t pid;
      ...
      while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
        ...
        if (pid == gSystemServerPid) {
          ALOGE("Exit zygote because system server (%d) has terminated", pid);
          kill(getpid(), SIGKILL); // 如果死亡的是SystemServer进程,zygote将退出
        }
      }
      ...
    }
    

    SigChldHandler函数接收到子进程死亡的信号后,除了调用waitpid()来防止子进程变“僵尸”外,还会判断死亡的子进程是否是SystemServer进程,如果是,Zygote进程会“自杀”,这样将导致Init进程杀死所有用户进程并重启Zygote。整个手机相当于重启了一扁,从而达到系统“软重启”的目的。

    3.在fork出SystemServer进程后,在fork出的进程中调用handleSystemServerProcess()来初始化SystemServer进程。

    private static void handleSystemServerProcess(
                ZygoteConnection.Arguments parsedArgs)
                throws ZygoteInit.MethodAndArgsCaller {
            // 关闭父进程zygote复制而来的Socket
            closeServerSocket(); 
            // 接SystemServer进程的umask设为0077(S_IRWXG|S_IRWXO),
            // 这样SystemServer创建的文件的属性就是0077,只有SystemServer进程可以访问。
            Os.umask(S_IRWXG | S_IRWXO);
    
            if (parsedArgs.niceName != null) {
                // 设置当前进程名为 "system_server"
                Process.setArgV0(parsedArgs.niceName);
            }
    
            final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
            if (systemServerClasspath != null) {
                // 执行dex优化操作
                performSystemServerDexOpt(systemServerClasspath);
            }
    
            if (parsedArgs.invokeWith != null) {// invokeWith通常为null
                String[] args = parsedArgs.remainingArgs;
                if (systemServerClasspath != null) {
                    String[] amendedArgs = new String[args.length + 2];
                    amendedArgs[0] = "-cp";
                    amendedArgs[1] = systemServerClasspath;
                    System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);
                }
                // 启动应用进程
                WrapperInit.execApplication(parsedArgs.invokeWith,
                        parsedArgs.niceName, parsedArgs.targetSdkVersion,
                        VMRuntime.getCurrentInstructionSet(), null, args);
            } else {
                ClassLoader cl = null;
                if (systemServerClasspath != null) {
                    //创建类加载器,并赋予当前线程
                    cl = createSystemServerClassLoader(systemServerClasspath,
                                                       parsedArgs.targetSdkVersion);
                    Thread.currentThread().setContextClassLoader(cl);
                }
                RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
            }
        }
    

    因为参数invokeWith通常为null,所以会调用RuntimeInit.zygoteInit()方法。在zygoteInit()方法中,它最终会以抛出MethodAndArgsCaller异常的方式返回,实现真正调用SystemServer类的main()方法。

    二、SystemServer的初始化
    SystemServer是一个java类,其main()方法中调用了对象的run()方法。

        public static void main(String[] args) {
            //先初始化SystemServer对象,再调用对象的run()方法
            new SystemServer().run();
        }
    
        private void run() {
            try {
                //当系统时间比1970年更早,就设置当前系统时间为1970年 
                if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
                    SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
                }
    
                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", "");
                }
    
                //变更虚拟机的库文件,对于Android 6.0默认采用的是libart.so
                SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
    
                if (SamplingProfilerIntegration.isEnabled()) {
                    SamplingProfilerIntegration.start();
                    mProfilerSnapshotTimer = new Timer();
                    //system_server每隔1小时采用一次,并保存结果到system_server文件
                    mProfilerSnapshotTimer.schedule(new TimerTask() {
                            @Override
                            public void run() {
                                SamplingProfilerIntegration.writeSnapshot("system_server", null);
                            }
                        }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);
                }
    
                VMRuntime.getRuntime().clearGrowthLimit();
                VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
                Build.ensureFingerprintProperty();
                Environment.setUserRequired(true);
                BaseBundle.setShouldDefuse(true);
                BinderInternal.disableBackgroundScheduling(true);
                BinderInternal.setMaxThreads(sMaxBinderThreads);
                android.os.Process.setThreadPriority(
                    android.os.Process.THREAD_PRIORITY_FOREGROUND);
                android.os.Process.setCanSelfBackground(false);
                // 主线程looper就在当前线程运行
                Looper.prepareMainLooper();
                //加载android_servers.so库,该库包含的源码在frameworks/base/services/目录下
                System.loadLibrary("android_servers");
                // 检查上次关机过程是否失败,该方法可能不会返回
                performPendingShutdown();
                // 初始化系统上下文
                createSystemContext();
                //创建系统服务管理
                mSystemServiceManager = new SystemServiceManager(mSystemContext);
                //将mSystemServiceManager添加到本地服务的成员sLocalServiceObjects
                LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
            }
    
            // 创建并运行所有的Java服务
            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);
            }
            // 进入处理消息的循环
            Looper.loop();
            throw new RuntimeException("Main thread loop unexpectedly exited");
        }
    

    main()方法的主要是有:
    1.调用时间,如果当前系统时间比1970年更早,就设置当前系统时间为1970年 。
    2.设置属性persist.sys.dalvik.vm.lib.2的值为当前虚拟机的运行库的路径。
    3.调整虚拟机堆的内存。设定虚拟机利用率为0.8。
    4.加载android_servers.so库。
    5.调用createSystemContext()来获取Context。
    6.创建SystemServiceManager的对象mSystemServiceManager,这个对象负责系统Service的启动。
    7.启动服务。startBootstrapServices(),startBootstrapServices(),startBootstrapServices()三大方法。
    8.调用Loop.loop(),进入处理消息的循环。

        private void createSystemContext() {
            //创建ActivityThread对象
            ActivityThread activityThread = ActivityThread.systemMain();
            //创建ContextImpl、LoadedApk对象
            mSystemContext = activityThread.getSystemContext();
            //设置主题
            mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
        }
    

    在createSystemContext()方法里,通过ActivityThread的静态方法systemMain()创建了一个activityThread。然后调用它的getSystemContext()方法来获取系统的Context,最后设置主题。

    接下来看看systemMain()方法。

        public static ActivityThread systemMain() {
            //对于低内存的设备,禁用硬件加速
            if (!ActivityManager.isHighEndGfx()) {
                ThreadedRenderer.disable(true);
            } else {
                ThreadedRenderer.enableForegroundTrimming();
            }
            // 创建ActivityThread
            ActivityThread thread = new ActivityThread();
            // 创建Application以及调用其onCreate()方法
            thread.attach(true);//代表是系统的应用进程
            return thread;
        }
    

    上面的代码主要是new了一个ActivityThread对象。
    同样的我们知道,ActivityThread是应用程序的主线程类,该类同时也存在一个main()主方法,zygote进程在启动过程的最后会在抛出的MethodAndArgsCaller异常中,通过反射来执行ActivityThread类的main()方法。那么这里为什么要用new来创建ActivityThread对象呢?
    实际上SystemServer不仅是一个单纯的后台进程,它也是一个运行着组件Service的进程,很多系统的对话框就是从SystemServer中显示出来的,因此,SystemServer本身也需要一个和APK应用类似的上下文环境,创建ActivityThread是获取这个环境的第一步,后面还需要创建SystemContext对象。ActivityThread的attach(boolean)方法中,传入参数true时,表示是在SystemServer中调用。如下代码:

        private void attach(boolean system) {
            sCurrentActivityThread = this;
            mSystemThread = system;
            if (!system) {//进入应用进程的处理流程
                ...
            } else { //进入系统进程。该情况只在SystemServer中处理,设置DDMS时看到的systemserver进程名为system_process
                android.ddm.DdmHandleAppName.setAppName("system_process",
                        UserHandle.myUserId());
                try {
                    mInstrumentation = new Instrumentation();
                    // 创建应用上下文SystemContext
                    ContextImpl context = ContextImpl.createAppContext(
                            this, getSystemContext().mPackageInfo);
                    // 创建Application
                    mInitialApplication = context.mPackageInfo.makeApplication(true, null);
                    // 调用Application的onCreate()方法
                    mInitialApplication.onCreate();
                } catch (Exception e) {
                    throw new RuntimeException(
                            "Unable to instantiate Application():" + e.toString(), e);
                }
            }
            ...
        }
    

    system为true时,创建了ContextImpl和Application对象,最后还调用了Application的onCreate()方法,完全模拟创建一个应用的过程。但是,创建应用上下文环境需要对应的一个apk文件,这个的apk文件是哪个呢?上面的参数中getSystemContext().mPackageInfo正是。
    通过跟踪getSystemContext()的代码,最终可以找到在ContextImpl类的createSystemContext(ActivityThread)方法中创建了一个LoadedApk对象。

        LoadedApk(ActivityThread activityThread) {
            mActivityThread = activityThread;
            mApplicationInfo = new ApplicationInfo();
            mApplicationInfo.packageName = "android";
            mPackageName = "android";
            ...
        }
    

    LoadedApk对象保存了一个apk文件的信息,它指明了将使用的包名为“android”,而framework-res.apk的包名正是“android”。因此,getSystemContext()方法返回的对象所对象的apk文件就是framework-res.apk。
    因此,ActivityThread的SystemMain()方法相当于创建了一个framework-res.apk的上下文环境。

    总结:
    SystemServer进程是一个应用进程访问底层资源的中间层代理,通过它来启动和管理AMS,PMS等众多服务。

    相关文章

      网友评论

        本文标题:Android源码学习--SystemServer进程

        本文链接:https://www.haomeiwen.com/subject/gwyoittx.html