Android 10.0系統啟動之SystemServer程序(一)

感謝您的閱讀與點贊!歡迎點選右上角關注:「大貓玩程式」

微信公眾號:大貓玩程式

Android 10.0系統啟動之SystemServer程序(一)

前幾節已經講完了Android10。0的Init啟動過程以及Zygote啟動流程,這一節主要講解SystemServer程序。

Android 10。0系統原始碼取經之路——啟動篇

Android系統架構淺析-「Android取經之路」

Android是怎麼啟動的-「Android取經之路」

Android 10。0系統啟動之init程序(二)-「Android取經之路」

Android 10。0系統啟動之init程序(二)-「Android取經之路」

Android 10。0系統啟動之init程序(三)-「Android取經之路」

Android 10。0系統啟動之init程序(四)-「Android取經之路」

Android 10。0系統啟動之Zygote程序(一)-「Android取經之路」

Android 10。0系統啟動之Zygote程序(二)-「Android取經之路」

Android 10。0系統啟動之Zygote程序(三)-「Android取經之路」

Android 10。0系統啟動之Zygote程序(四)-「Android取經之路」

1。 概述

上一節講解了Zygote程序的整個啟動流程。Zygote是所有應用的鼻祖。SystemServer和其他所有Dalivik虛擬機器程序都是由Zygote fork而來。Zygote fork的第一個程序就是SystemServer,其在手機中的程序名為 system_server。

system_server 程序承載著整個framework的核心服務,例如建立 ActivityManagerService、PowerManagerService、DisplayManagerService、PackageManagerService、WindowManagerService、LauncherAppsService等90多個核心繫統服務。這些服務以不同的執行緒方式存在於system_server這個程序中。

接下來,就讓我們透過Android系統原始碼一起來分析一下system_server的整個啟動過程。

2。 核心原始碼

/frameworks/base/core/java/com/android/internal/os/ZygoteInit。java/frameworks/base/core/java/com/android/internal/os/RuntimeInit。java/frameworks/base/core/java/com/android/internal/os/Zygote。java/frameworks/base/services/java/com/android/server/SystemServer。java/frameworks/base/services/core/java/com/android/serverSystemServiceManager。java/frameworks/base/services/core/java/com/android/ServiceThread。java/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService。java/frameworks/base/core/java/android/app/ActivityThread。java/frameworks/base/core/java/android/app/LoadedApk。java/frameworks/base/core/java/android/app/ContextImpl。java/frameworks/base/core/jni/AndroidRuntime。cpp/frameworks/base/core/jni/com_android_internal_os_ZygoteInit。cpp/frameworks/base/cmds/app_process/app_main。cpp

3。 架構

3.1 架構圖

SystemServer 被Zygote程序fork出來後,用來建立ActivityManagerService、PowerManagerService、DisplayManagerService、PackageManagerService、WindowManagerService、LauncherAppsService等80多個核心繫統服務

Android 10.0系統啟動之SystemServer程序(一)

3.2 服務啟動

Android 10.0系統啟動之SystemServer程序(一)

4。 原始碼分析

4。1 SystemServer fork流程分析

Android 10.0系統啟動之SystemServer程序(一)

4.1.1 [ZygoteInit.java] main()

說明:

Zygote程序,透過fork()函式,最終孵化出system_server的程序,透過反射的方法啟動SystemServer。java的main()方法

原始碼:

public static void main(String argv[]) { ZygoteServer zygoteServer = null; 。。。 try { zygoteServer = new ZygoteServer(isPrimaryZygote); if (startSystemServer) { //fork system_server Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer); // {@code r == null} in the parent (zygote) process, and {@code r != null} in the // child (system_server) process。 if (r != null) { r。run(); //啟動SystemServer。java的main() return; //Android 8。0之前是透過拋異常的方式來啟動,這裡是直接return出去,用來清空棧,提高棧幀利用率 } } caller = zygoteServer。runSelectLoop(abiList); } catch (Throwable ex) { Log。e(TAG, “System zygote died with exception”, ex); throw ex; } finally { if (zygoteServer != null) { zygoteServer。closeServerSocket(); } } if (caller != null) { caller。run(); } 。。。}

4.1.2 [ZygoteInit.java] forkSystemServer()

說明:

準備引數,用來進行system_server的fork,從引數可知,pid=1000,gid=1000,程序名nick-name=system_server

當有兩個Zygote程序時,需要等待第二個Zygote建立完成。由於fork時會複製socket,因此,在fork出system_server程序後,需要關閉Zygote原有的socket

原始碼:

private static Runnable forkSystemServer(String abiList, String socketName, ZygoteServer zygoteServer) { …… //引數準備,uid和gid都是為1000 String args[] = { “——setuid=1000”, “——setgid=1000”, “——setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,” + “1024,1032,1065,3001,3002,3003,3006,3007,3009,3010”, “——capabilities=” + capabilities + “,” + capabilities, “——nice-name=system_server”, “——runtime-args”, “——target-sdk-version=” + VMRuntime。SDK_VERSION_CUR_DEVELOPMENT, “com。android。server。SystemServer”, }; ZygoteArguments parsedArgs = null; int pid; try { //將上面準備的引數,按照ZygoteArguments的風格進行封裝 parsedArgs = new ZygoteArguments(args); Zygote。applyDebuggerSystemProperty(parsedArgs); Zygote。applyInvokeWithSystemProperty(parsedArgs); //透過fork“分裂”出子程序system_server /* Request to fork the system server process */ pid = Zygote。forkSystemServer( parsedArgs。mUid, parsedArgs。mGid, parsedArgs。mGids, parsedArgs。mRuntimeFlags, null, parsedArgs。mPermittedCapabilities, parsedArgs。mEffectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } //進入子程序system_server if (pid == 0) { // 處理32_64和64_32的情況 if (hasSecondZygote(abiList)) { waitForSecondaryZygote(socketName); //需要等待第二個Zygote建立完成 } // fork時會copy socket,Zygote原有的socket需要關閉 zygoteServer。closeServerSocket(); // system server程序處理自己的工作 return handleSystemServerProcess(parsedArgs); } return null;}

4.1.3 [Zygote.java] forkSystemServer()

說明:

這裡的nativeForkSystemServer()最終是透過JNI,呼叫Nativate C空間的com_android_internal_os_Zygote_nativeForkSystemServer() 來fork system_server

原始碼:

public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags, int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) { ZygoteHooks。preFork(); // Resets nice priority for zygote process。 resetNicePriority(); //呼叫native的方法來fork system_server //最終呼叫native的方法:com_android_internal_os_Zygote_nativeForkSystemServer int pid = nativeForkSystemServer( uid, gid, gids, runtimeFlags, rlimits, permittedCapabilities, effectiveCapabilities); // Enable tracing as soon as we enter the system_server。 if (pid == 0) { Trace。setTracingEnabled(true, runtimeFlags); } ZygoteHooks。postForkCommon(); return pid;}

[com_android_internal_os_Zygote.cpp]

說明:

JNI註冊的對映關係

static const JNINativeMethod gMethods[] = { { “nativeForkSystemServer”, “(II[II[[IJJ)I”, (void *) com_android_internal_os_Zygote_nativeForkSystemServer },}

4.1.4 [com_android_internal_os_Zygote.cpp]

com_android_internal_os_Zygote_nativeForkSystemServer()

說明:

透過 SpecializeCommon進行fork,pid返回0時,表示當前為system_server子程序

當pid >0 時,是進入父程序,即Zygote程序,透過waitpid 的WNOHANG 非阻塞方式來監控system_server程序掛掉,如果掛掉後重啟Zygote程序。

現在使用的Android系統大部分情況下是64位的,會存在兩個Zygote,當system_server掛掉後,只啟動Zygote64這個父程序

原始碼:

static jint com_android_internal_os_Zygote_nativeForkSystemServer( JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities, jlong effective_capabilities) { pid_t pid = ForkCommon(env, true, fds_to_close, fds_to_ignore); if (pid == 0) { //進入子程序 SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, permitted_capabilities, effective_capabilities, MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true, false, nullptr, nullptr); } else if (pid > 0) { //進入父程序,即zygote程序 ALOGI(“System server process %d has been created”, pid); int status; //用waitpid函式獲取狀態發生變化的子程序pid //waitpid的標記為WNOHANG,即非阻塞,返回為正值就說明有程序掛掉了 if (waitpid(pid, &status, WNOHANG) == pid) { //當system_server程序死亡後,重啟zygote程序 ALOGE(“System server process %d has died。 Restarting Zygote!”, pid); RuntimeAbort(env, __LINE__, “System server process has died。 Restarting Zygote!”); } 。。。 } return pid;}

4.1.5 [com_android_internal_os_Zygote.cpp] ForkCommon

說明:

從Zygote孵化出一個程序的使用程式

原始碼:

static pid_t ForkCommon(JNIEnv* env, bool is_system_server, const std::vector& fds_to_close, const std::vector& fds_to_ignore) { //設定子程序的signal SetSignalHandlers(); //在fork的過程中,臨時鎖住SIGCHLD BlockSignal(SIGCHLD, fail_fn); //fork子程序,採用copy on write方式,這裡執行一次,會返回兩次 //pid=0 表示Zygote fork SystemServer這個子程序成功 //pid > 0 表示SystemServer 的真正的PID pid_t pid = fork(); if (pid == 0) { //進入子程序 // The child process。 PreApplicationInit(); // 關閉並清除檔案描述符 // Clean up any descriptors which must be closed immediately DetachDescriptors(env, fds_to_close, fail_fn); 。。。 } else { ALOGD(“Forked child process %d”, pid); } //fork結束,解鎖 UnblockSignal(SIGCHLD, fail_fn); return pid;}

4.1.6 [Zygcom_android_internal_os_Zygoteote.cpp] SpecializeCommon

說明:

system_server程序的一些排程配置

原始碼:

static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids, jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities, jlong effective_capabilities, jint mount_external, jstring managed_se_info, jstring managed_nice_name, bool is_system_server, bool is_child_zygote, jstring managed_instruction_set, jstring managed_app_data_dir) { 。。。 bool use_native_bridge = !is_system_server && instruction_set。has_value() && android::NativeBridgeAvailable() && android::NeedsNativeBridge(instruction_set。value()。c_str()); if (!is_system_server && getuid() == 0) { //對於非system_server子程序,則建立程序組 const int rc = createProcessGroup(uid, getpid()); if (rc == -EROFS) { ALOGW(“createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?”); } else if (rc != 0) { ALOGE(“createProcessGroup(%d, %d) failed: %s”, uid, /* pid= */ 0, strerror(-rc)); } } SetGids(env, gids, fail_fn); //設定設定group SetRLimits(env, rlimits, fail_fn); //設定資源limit if (use_native_bridge) { // Due to the logic behind use_native_bridge we know that both app_data_dir // and instruction_set contain values。 android::PreInitializeNativeBridge(app_data_dir。value()。c_str(), instruction_set。value()。c_str()); } if (setresgid(gid, gid, gid) == -1) { fail_fn(CREATE_ERROR(“setresgid(%d) failed: %s”, gid, strerror(errno))); } 。。。 //selinux上下文 if (selinux_android_setcontext(uid, is_system_server, se_info_ptr, nice_name_ptr) == -1) { fail_fn(CREATE_ERROR(“selinux_android_setcontext(%d, %d, \”%s\“, \”%s\“) failed”, uid, is_system_server, se_info_ptr, nice_name_ptr)); } //設定執行緒名為system_server,方便除錯 if (nice_name。has_value()) { SetThreadName(nice_name。value()); } else if (is_system_server) { SetThreadName(“system_server”); } // Unset the SIGCHLD handler, but keep ignoring SIGHUP (rationale in SetSignalHandlers)。 //設定子程序的signal訊號處理函式為預設函式 UnsetChldSignalHandler(); if (is_system_server) { //對應 Zygote。java 的callPostForkSystemServerHooks() env->CallStaticVoidMethod(gZygoteClass, gCallPostForkSystemServerHooks); if (env->ExceptionCheck()) { fail_fn(“Error calling post fork system server hooks。”); } //對應ZygoteInit。java 的 createSystemServerClassLoader() //預取系統伺服器的類載入器。這樣做是為了儘早地繫結適當的系統伺服器selinux域。 env->CallStaticVoidMethod(gZygoteInitClass, gCreateSystemServerClassLoader); if (env->ExceptionCheck()) { // Be robust here。 The Java code will attempt to create the classloader // at a later point (but may not have rights to use AoT artifacts)。 env->ExceptionClear(); } 。。。 } //等價於呼叫zygote。java 的callPostForkChildHooks() env->CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags, is_system_server, is_child_zygote, managed_instruction_set); if (env->ExceptionCheck()) { fail_fn(“Error calling post fork hooks。”); }}

4.1.7 [ZygoteInit.java] handleSystemServerProcess

說明:

建立類載入器,並賦予當前執行緒,其中環境變數SYSTEMSERVERCLASSPATH,主要是service。jar、ethernet-service。jar和wifi-service。jar這三個jar包

export SYSTEMSERVERCLASSPATH=/system/framework/services。jar:/system/framework/ethernet-service。jar:/system/framework/wifi-service。jar

原始碼:

private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) { if (parsedArgs。mNiceName != null) { Process。setArgV0(parsedArgs。mNiceName); //設定當前程序名為“system_server” } final String systemServerClasspath = Os。getenv(“SYSTEMSERVERCLASSPATH”); if (systemServerClasspath != null) { //執行dex最佳化操作 if (performSystemServerDexOpt(systemServerClasspath)) { sCachedSystemServerClassLoader = null; } 。。。 } if (parsedArgs。mInvokeWith != null) { String[] args = parsedArgs。mRemainingArgs; //如果我們有一個非空系統伺服器類路徑,我們將不得不復制現有的引數並將類路徑附加到它。 //當我們執行一個新程序時,ART將正確地處理類路徑。 if (systemServerClasspath != null) { String[] amendedArgs = new String[args。length + 2]; amendedArgs[0] = “-cp”; amendedArgs[1] = systemServerClasspath; System。arraycopy(args, 0, amendedArgs, 2, args。length); args = amendedArgs; } //啟動應用程序 WrapperInit。execApplication(parsedArgs。mInvokeWith, parsedArgs。mNiceName, parsedArgs。mTargetSdkVersion, VMRuntime。getCurrentInstructionSet(), null, args); throw new IllegalStateException(“Unexpected return from WrapperInit。execApplication”); } else { // 建立類載入器,並賦予當前執行緒 createSystemServerClassLoader(); ClassLoader cl = sCachedSystemServerClassLoader; if (cl != null) { Thread。currentThread()。setContextClassLoader(cl); } //system_server進入此分支 return ZygoteInit。zygoteInit(parsedArgs。mTargetSdkVersion, parsedArgs。mRemainingArgs, cl); }}

4.1.8 [ZygoteInit.java] zygoteInit

說明:

基礎配置,並進行應用初始化,返回物件

原始碼:

public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) { Trace。traceBegin(Trace。TRACE_TAG_ACTIVITY_MANAGER, “ZygoteInit”); RuntimeInit。redirectLogStreams(); //重定向log輸出 RuntimeInit。commonInit(); //通用的一些初始化 ZygoteInit。nativeZygoteInit(); // zygote初始化 // 應用初始化 return RuntimeInit。applicationInit(targetSdkVersion, argv, classLoader);}

4.1.9 [RuntimeInit.java] commonInit

說明:

配置log、時區、http userAgent等基礎資訊

原始碼:

protected static final void commonInit() { LoggingHandler loggingHandler = new LoggingHandler(); // 設定預設的未捕捉異常處理方法 RuntimeHooks。setUncaughtExceptionPreHandler(loggingHandler); Thread。setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler)); // 設定時區,透過屬性讀出中國時區為“Asia/Shanghai” RuntimeHooks。setTimeZoneIdSupplier(() -> SystemProperties。get(“persist。sys。timezone”)); //重置log配置 LogManager。getLogManager()。reset(); new AndroidConfig(); //設定預設的HTTP User-agent格式,用於 HttpURLConnection String userAgent = getDefaultUserAgent(); System。setProperty(“http。agent”, userAgent); /* * Wire socket tagging to traffic stats。 */ //設定socket的tag,用於網路流量統計 NetworkManagementSocketTagger。install(); 。。。}

4.1.10 [ZygoteInit.java] nativeZygoteInit

說明:

nativeZygoteInit 透過反射,進入com_android_internal_os_ZygoteInit_nativeZygoteInit

原始碼:

[AndroidRuntime。cpp]int register_com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env){ const JNINativeMethod methods[] = { { “nativeZygoteInit”, “()V”, (void*) com_android_internal_os_ZygoteInit_nativeZygoteInit }, }; return jniRegisterNativeMethods(env, “com/android/internal/os/ZygoteInit”, methods, NELEM(methods));}gCurRuntime = this;static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz){ //此處的gCurRuntime為AppRuntime,是在AndroidRuntime。cpp中定義的 gCurRuntime->onZygoteInit();}

[app_main.cpp]

virtual void onZygoteInit(){ sp proc = ProcessState::self(); ALOGV(“App process: starting thread pool。\n”); proc->startThreadPool(); //啟動新binder執行緒}

4.1.11 [RuntimeInit.java] applicationInit

說明:

透過引數解析,得到args。startClass = com。android。server。SystemServer

原始碼:

protected static Runnable applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) { //true代表應用程式退出時不呼叫AppRuntime。onExit(),否則會在退出前呼叫 nativeSetExitWithoutCleanup(true); // We want to be fairly aggressive about heap utilization, to avoid // holding on to a lot of memory that isn‘t needed。 //設定虛擬機器的記憶體利用率引數值為0。75 VMRuntime。getRuntime()。setTargetHeapUtilization(0。75f); VMRuntime。getRuntime()。setTargetSdkVersion(targetSdkVersion); final Arguments args = new Arguments(argv); //解析引數 。。。 // Remaining arguments are passed to the start class’s static main //呼叫startClass的static方法 main() return findStaticMain(args。startClass, args。startArgs, classLoader);}

4.1.12 [RuntimeInit.java] findStaticMain

說明:

拿到SystemServer的main()方法,並返回 MethodAndArgsCaller()物件

原始碼:

protected static Runnable findStaticMain(String className, String[] argv, ClassLoader classLoader) { Class<?> cl; try { //拿到com。android。server。SystemServer 的類物件 cl = Class。forName(className, true, classLoader); } catch (ClassNotFoundException ex) { throw new RuntimeException( “Missing class when invoking static main ” + className, ex); } Method m; try { //得到SystemServer的main()方法, m = cl。getMethod(“main”, new Class[] { String[]。class }); } catch (NoSuchMethodException ex) { throw new RuntimeException( “Missing static main on ” + className, ex); } catch (SecurityException ex) { throw new RuntimeException( “Problem getting static main on ” + className, ex); } int modifiers = m。getModifiers(); if (! (Modifier。isStatic(modifiers) && Modifier。isPublic(modifiers))) { throw new RuntimeException( “Main method is not public and static on ” + className); } //把MethodAndArgsCaller的物件返回給ZygoteInit。main()。這樣做好處是能清空棧幀,提高棧幀利用率 //清除了設定程序所需的所有堆疊幀 return new MethodAndArgsCaller(m, argv);}

4.1.13 [RuntimeInit.java] MethodAndArgsCaller

說明:

最終在ZygoteInit。java的main(),呼叫這裡的run()來啟動SystemServer。java的main(),真正進入SystemServer程序

原始碼:

static class MethodAndArgsCaller implements Runnable { /** method to call */ private final Method mMethod; /** argument array */ private final String[] mArgs; public MethodAndArgsCaller(Method method, String[] args) { mMethod = method; mArgs = args; } public void run() { try { //根據傳遞過來的引數,可知此處透過反射機制呼叫的是SystemServer。main()方法 mMethod。invoke(null, new Object[] { mArgs }); } catch (IllegalAccessException ex) { throw new RuntimeException(ex); } catch (InvocationTargetException ex) { Throwable cause = ex。getCause(); if (cause instanceof RuntimeException) { throw (RuntimeException) cause; } else if (cause instanceof Error) { throw (Error) cause; } throw new RuntimeException(ex); } }}

下一節會講解SystemServer 啟動的流程以及不同階段的服務啟動,歡迎繼續關注