Android面试专栏Android源码家Android知识

Android源码学习--SystemServer进程

2017-02-13  本文已影响447人  PrivateGO

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等众多服务。

上一篇下一篇

猜你喜欢

热点阅读