1. 程式人生 > >Android7.0 系統啟動流程---system_server

Android7.0 系統啟動流程---system_server

今天主要分析Android啟動流程,重點是system_server相關知識。

一、Android系統啟動流程

Android正常啟動流程如下:
Step1 系統加電,執行bootloader。Bootloader負責初始化軟體執行所需要的最小硬體環境,最後載入核心到記憶體。
Step2 核心載入進記憶體後,將首先進入核心引導階段,在核心引導階段的最後,呼叫start_kenel進入核心啟動階段。start_kenel最終啟動使用者空間的init程式。
Step3 init程式負責解析init.rc配置檔案,開啟系統守護程序。兩個最重要的守護程序是zygote程序和ServiceManager,zygote是Android啟動的第一個Dalvik虛擬機器,ServiceManager是Binder通訊的基礎。
Step4

zygote虛擬機器啟動子程序system_server,在system_server中開啟了核心系統服務,並將系統服務新增到ServiceManager中,然後系統進入SystemReady狀態。
Step5 在SystemReady狀態,ActivityManagerService與zygote中的socket通訊,通過zygote啟動home應用,進入系統桌面。

從Step3開始,init啟動後,上層的實現。
Step1 init啟動的核心Daemon服務包括Android的第一個Dalvik虛擬機器zygote。
Step2 zygote定義一個socket,用於接受ActivityManagerService啟動應用的請求。
Step3

zygote通過fork系統呼叫建立system_server程序
Step4 在system_server程序中,將會啟動系統核心服務以及其他服務。
Step5 系統服務啟動後會註冊到ServiceManager中,用於Binder通訊。
Step6 ActivityManagerService進入systemReady狀態。
Step7 在systemReady狀態,ActivityManagerService會與zygote的Socket通訊,請求啟動Home。
Step8 zygote收到AMS的連線請求後,執行runSelectLoopMode處理請求。
Step9
zygote處理請求會通過forkAndSpecialize啟動新的應用程序,並最終啟動Home。

二、system_server啟動過程

在Step3,系統會建立system_server,下面開始分析system_server建立過程。
系統在預載入了共享資源後,編開始啟動system_server程序,system_server是理解framework層的基礎。Android中所有的系統服務都由它啟動,它的異常會導致zygote的自殺重啟,這樣整個java就崩潰了。
System_server的啟動入口是startSystemServer方法,位於frameworks/base/core/java/com/android/internal/os/ZygoteInit.java。
在ZygoteInit的main函式,呼叫了方法startSystemServer。

  public static void main(String argv[]) {
        ...
        String socketName = "zygote";
        ...
        try {            
           ...
           if (startSystemServer) {
                startSystemServer(abiList, socketName);
            }  
            ....

分析startSystemServer方法:

 /**
     * Prepare the arguments and fork for the system server process.
     */
    private static boolean startSystemServer(String abiList, String socketName)
            throws MethodAndArgsCaller, RuntimeException {
        long capabilities = posixCapabilitiesAsBits(
            OsConstants.CAP_IPC_LOCK,
            OsConstants.CAP_KILL,
            OsConstants.CAP_NET_ADMIN,
            OsConstants.CAP_NET_BIND_SERVICE,
            OsConstants.CAP_NET_BROADCAST,
            OsConstants.CAP_NET_RAW,
            OsConstants.CAP_SYS_MODULE,
            OsConstants.CAP_SYS_NICE,
            OsConstants.CAP_SYS_RESOURCE,
            OsConstants.CAP_SYS_TIME,
            OsConstants.CAP_SYS_TTY_CONFIG
        );
        /* Containers run without this capability, so avoid setting it in that case */
        if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {
            capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);
        }
        /* Hardcoded command line to start the system server */
        /*  設定啟動system_server的命令列引數 */
        String args[] = {
            "--setuid=1000", //設定使用者的ID為1000,這個UID代表系統許可權
            "--setgid=1000",
            /// M: ANR mechanism for system_server add shell(2000) group to access
            ///    /sys/kernel/debug/tracing/tracing_on
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,2000," +
                "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 {
            //將陣列分解成Arguments型別的物件,過程很簡單
            parsedArgs = new ZygoteConnection.Arguments(args);
            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

            /* Request to fork the system server process */
            //呼叫系統fork函式建立子程序,這個子程序就是sysytem_server
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        //pid為0說明在子程序system_server中
        if (pid == 0) {

            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }
            //在子程序system_server中呼叫了handleSystemServerProcess方法
            handleSystemServerProcess(parsedArgs);
        }
        //在父程序中返回
        return true;
    }

到這裡,zygote做了第一次分裂,forck出系統服務的總管system_server程序,這個過程分為以下兩個重要的步驟:
1)、通過forkSystemServer建立system_server子程序。
2)、在子程序中呼叫handleSystemServerProcess方法。

2.1 通過forkSystemServer建立system_server子程序
啟動system_server的第一步便是呼叫zygote的system_server方法,在該方法內部將呼叫Native方法nativeForkSystemServer,來完成啟動system_server程序的任務。nativeForkSystemServer的JNI層實現方法位於frameworks/base/core/jni/com_android_internal_os_Zygote.cpp中,方法名為com_android_internal_os_Zygote_nativeForkSystemServer()。

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) {
            //間接呼叫了ForkAndSpecializeCommom() 函式
  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) {//pid>0,則是在system_server的父程序zygote中
      // The zygote process checks whether the child process has died or not.
      ALOGI("System server process %d has been created", pid);
      gSystemServerPid = pid;//在虛擬機器中記錄system_server的程序ID
      // There is a slight window that the system server process has crashed
      // but it went unnoticed because we haven't published its pid yet. So
      // we recheck here just to make sure that all is well.
      int status;
      //退出前,重新檢查sysem_server程序是否有異常,如果異常退出,
      //則zygote直接自殺,因為在zygote的服務項中配置了onrestart這個*option,
      //所以zogote自殺後,init程序會重新啟動它
      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;
}

在這裡,系統會檢查system_server程序是否啟動成功,如果啟動失敗,將導致zygote重啟。system_server負責構建系統服務,如果啟動失敗,Android系統也就無法啟動,所以必須重啟zygote、因此Dalvik_dalvik_system_Zygote_forkSystemServer方法的功能分成兩部分:
1)啟動system_server程序。
2)監控system_server程序的啟動結果。

2.1.1 啟動system_server程序
這部分功能由ForkAndSpecializeCommon()函式實現,位於本類中,

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();
                                     //呼叫fork()函式
                                     pid_t pid = fork();
                                     if (pid == 0){
                                         ......//子程序
                                     }else if(pid > 0) {
                                         ......//父程序處理
                                     }
                                     return pid;
}

ForkAndSpecializeCommon函式通過fork()系統函式建立子程序system_server,並在建立system_server前做了重要工作:註冊訊號處理函式。該訊號處理函式的作用就是代表子執行緒退出的訊號。在setSigChldHandler()函式:

// Configures the SIGCHLD handler for the zygote process. This is configured
// very late, because earlier in the runtime we may fork() and exec()
// other processes, and we want to waitpid() for those rather than
// have them be harvested immediately.
//
// This ends up being called repeatedly before each fork(), but there's
// no real harm in that.
static void SetSigChldHandler() {
    //這裡是非常通用的Linux註冊訊號處理函式的流程,呼叫系統函式sigaction()處理
    //SIGCHLD訊號,具體的處理函式是SigChldHandler。SIGCHLD訊號是子程序退出訊號
  struct sigaction sa;
  memset(&sa, 0, sizeof(sa));
  sa.sa_handler = SigChldHandler;

  int err = sigaction(SIGCHLD, &sa, NULL);
  if (err < 0) {
    ALOGW("Error setting SIGCHLD handler: %s", strerror(errno));
  }
}

SetSigChldHandler註冊了訊號處理函式sigChldHandler,處理的訊號便是SIGCHLD,代表子程序退出訊號。

2.1.2 監控system_server程序的啟動結果
當子程序退出時,由SigChldHandler處理該訊號,接下來分析sigchldHandler處理SIGCHLD訊號。

// This signal handler is for zygote mode, since the zygote must reap its children
static void SigChldHandler(int /*signal_number*/) {
  pid_t pid;
  int status;

  // It's necessary to save and restore the errno during this function.
  // Since errno is stored per thread, changing it here modifies the errno
  // on the thread on which this signal handler executes. If a signal occurs
  // between a call and an errno check, it's possible to get the errno set
  // here.
  // See b/23572286 for extra information.
  int saved_errno = errno;
//呼叫系統函式waitpid等待子程序退出
//第一個引數-1表示等待任何子程序
//第二個引數status用於收集子程序退出時的狀態
//第三個引數WNOHANG表示如果沒有子程序退出,不需要阻塞
  while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
     // Log process-death status that we care about.  In general it is
     // not safe to call LOG(...) from a signal handler because of
     // possible reentrancy.  However, we know a priori that the
     // current implementation of LOG() is safe to call from a SIGCHLD
     // handler in the zygote process.  If the LOG() implementation
     // changes its locking strategy or its use of syscalls within the
     // lazy-init critical section, its use here may become unsafe.
    if (WIFEXITED(status)) {
      if (WEXITSTATUS(status)) {
        ALOGI("Process %d exited cleanly (%d)", pid, WEXITSTATUS(status));
      }
    } else if (WIFSIGNALED(status)) {
      if (WTERMSIG(status) != SIGKILL) {
        ALOGI("Process %d exited due to signal (%d)", pid, WTERMSIG(status));
      }
      if (WCOREDUMP(status)) {
        ALOGI("Process %d dumped core.", pid);
      }
    }

    // If the just-crashed process is the system_server, bring down zygote
    // so that it is restarted by init and system server will be restarted
    // from there.
    if (pid == gSystemServerPid) {
      ALOGE("Exit zygote because system server (%d) has terminated", pid);
      //如果退出的是system_server程序,zygote重啟,SIGKILL是自殺訊號。
      //雖然zygote自殺了,但是init程序會負責救活它。
      kill(getpid(), SIGKILL);
    }
  }

從forkSystemServer函式的執行過程可以看出:zygote建立system_server程序是十分謹慎的,不但在建立之初判斷system_server是否退出,在建立後還專門註冊訊號處理函式監控system_server的執行狀態。如果system_server出現意外,zygote也會自殺,導致整個java世界崩潰。
接下來分析fork出system_server後的處理。

2.2 在子程序中呼叫handleSystemServerProcess方法
system_server程序啟動之後,便開始呼叫handleSystemServerProcess方法,該方法位於ZygoteInit.java中,程式碼如下:

    /**
     * Finish remaining work for the newly forked system server process.
     */
    private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws ZygoteInit.MethodAndArgsCaller {

        // 關閉之前fork操作時,從zygote繼承下來的socket
        closeServerSocket();

        // 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);
        }

        // 根據invokeWith引數,執行一個shell命令
        if (parsedArgs.invokeWith != null) {
            String[] args = parsedArgs.remainingArgs;
            // If we have a non-null system server class path, we'll have to duplicate the
            // existing arguments and append the classpath to it. ART will handle the classpath
            // correctly when we exec a new process.
            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);
            }

            /*
             * Pass the remaining arguments to SystemServer.
             */
             //呼叫zygoteInit方法,傳入引數
            RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);
        }

        /* should never reach here */
    }

system_server生成之後,迅速進入工作狀態,執行handleSystemServerProcess。在該方法中,首先做了一些清理和初始化工作,接著呼叫RuntimeInit.zygoteInit()方法。
RuntimeInit.java位於frameworks\base\core\java\com\android\internal\os\RuntimeInit.java,

/**
     * 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>
     *
     * Current recognized args:
     * <ul>
     *   <li> <code> [--] &lt;start class name&gt;  &lt;args&gt;
     * </ul>
     *
     * @param targetSdkVersion target SDK version
     * @param argv arg strings
     */
    public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");

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

        commonInit();
        nativeZygoteInit();
        applicationInit(targetSdkVersion, argv, classLoader);
    }

zygoteInit封裝了對四個方法的呼叫,對應四個步驟試下 不同的初始化操作,接下來分析四步。

2.2.1 redirectLogStrreams() 方法重定向標準I/O操作
redirectLogStreams()方法重定向Java標準I/O操作到Android日誌系統。

   /**
     * Redirect System.out and System.err to the Android log.
     */
    public static void redirectLogStreams() {
        System.out.close();
        System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
        System.err.close();
        System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));
    }

2.2.2 commonInit() 方法初始化通用設定

    private static final void commonInit() {
        if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");

        /* set default handler; this applies to all threads in the VM */
        //設定未不會異常的預設處理函式
        Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());

        /*
         * Install a TimezoneGetter subclass for ZoneInfo.db
         */
         //獲取persist.sys.timezone 屬性
        TimezoneGetter.setInstance(new TimezoneGetter() {
            @Override
            public String getId() {
                return SystemProperties.get("persist.sys.timezone");
            }
        });
        TimeZone.setDefault(null);

        /*
         * Sets handler for java.util.logging to use Android log facilities.
         * The odd "new instance-and-then-throw-away" is a mirror of how
         * the "java.util.logging.config.class" system property works. We
         * can't use the system property here since the logger has almost
         * certainly already been initialized.
         */
         //Android Log配置
        LogManager.getLogManager().reset();
        new AndroidConfig();

        /*
         * Sets the default HTTP User-Agent used by HttpURLConnection.
         */
         //預設的HTTP User-Agent,用於HTTP連線
        String userAgent = getDefaultUserAgent();
        System.setProperty("http.agent", userAgent);

        /*
         * Wire socket tagging to traffic stats.
         */
        NetworkManagementSocketTagger.install();//網路相關

        /*
         * If we're running in an emulator launched with "-trace", put the
         * VM into emulator trace profiling mode so that the user can hit
         * F9/F10 at any time to capture traces.  This has performance
         * consequences, so it's not something you want to do always.
         */
         //模擬器上面的trace除錯
        String trace = SystemProperties.get("ro.kernel.android.tracing");
        if (trace.equals("1")) {
            Slog.i(TAG, "NOTE: emulator trace profiling enabled");
            Debug.enableEmulatorTraceOutput();
        }

2.2.3 onZygoteInit 方法開啟Binder通訊
nativeZygoteInit是一個Native方法,其JNI實現方法位於frameworks\base\core\jni\AndroidRuntime.cpp,方法名為com_android_internal_os_RuntimeInit_nativeZygoteInit,具體程式碼:

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

onZygoteInit開啟了sysytem_serve的Binder通道。

2.2.4 invokeStaticMain方法丟擲異常

這樣,system_server程序已經基本啟動完成,之後system_server程序會啟動系統核心服務,以及其他服務。