標籤:android 源碼 系統
在上一篇博文中我們進行了有關Zygote進程的分析,我們知道Zygote進程建立了一個重要的進程–system_server進程後就進入了無限迴圈中,之後Android系統中的重要任務就交給了system_server進程,作為zygote的嫡長子進程,system_server進程的意義非凡,今天我們來分析一下system_server進程。
建立system_server進程
在ZygoteInit中main方法中,通過調用startSystemServer方法開啟了system_server進程。該方法主要為建立system_server進程準備了一些參數,並調用本地方法forkSystemServer建立system_server進程。讓我們來看一下startSystemServer方法的代碼:
private static boolean startSystemServer() throws MethodAndArgsCaller, RuntimeException { String args[] = { "--setuid=1000", "--setgid=1000", "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007", "--capabilities=130104352,130104352", "--runtime-init", "--nice-name=system_server", "com.android.server.SystemServer", }; ZygoteConnection.Arguments parsedArgs = null; int pid; try { parsedArgs = new ZygoteConnection.Arguments(args); ZygoteConnection.applyDebuggerSystemProperty(parsedArgs); ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs); /* 建立system_server進程 */ pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } /* 子進程中執行 */ if (pid == 0) { handleSystemServerProcess(parsedArgs); } return true; }
這裡的代碼並不複雜,可以看到,他調用了forkSystemServer方法來建立一個新的進程,之後在子進程,即system_server進程中執行handleSystemServerProcess方法。下面我們來看一下forkSystemServer方法,它是一個native方法對應的源檔案在dalvik\vm\native\dalvik_system_Zygote.cpp中。代碼如下:
static void Dalvik_dalvik_system_Zygote_forkSystemServer( const u4* args, JValue* pResult){ pid_t pid; pid = forkAndSpecializeCommon(args, true); /* zygote進程檢查其子進程是否死掉 */ if (pid > 0) { int status; ALOGI("System server process %d has been created", pid); gDvm.systemServerPid = pid; /* 如果system_server進程退出,則zygote進程也會被殺掉 */ if (waitpid(pid, &status, WNOHANG) == pid) { ALOGE("System server process %d has died. Restarting Zygote!", pid); kill(getpid(), SIGKILL); } } RETURN_INT(pid);}
從代碼中可以看到在forkAndSpecializeCommon方法中,我們建立了子進程,並返回了子進程id,接下來我檢查如果system_server進程是否退出,若是的話則zygote進程也將會被被幹掉,由此可見其重要性。接下來我們來看forkAndSpecializeCommon的代碼,這個system_server進程的建立真的是千峰百轉啊。。。
static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer){ pid_t pid; uid_t uid = (uid_t) args[0]; gid_t gid = (gid_t) args[1]; ArrayObject* gids = (ArrayObject *)args[2]; u4 debugFlags = args[3]; ArrayObject *rlimits = (ArrayObject *)args[4]; u4 mountMode = MOUNT_EXTERNAL_NONE; int64_t permittedCapabilities, effectiveCapabilities; char *seInfo = NULL; char *niceName = NULL; //傳入參數isSystemServer為true if (isSystemServer) { permittedCapabilities = args[5] | (int64_t) args[6] << 32; effectiveCapabilities = args[7] | (int64_t) args[8] << 32; } else { ...... } if (!gDvm.zygote) { dvmThrowIllegalStateException( "VM instance not started with -Xzygote"); return -1; } // 在第一次調用fork函數之前需要調用 if (!dvmGcPreZygoteFork()) { ALOGE("pre-fork heap failed"); dvmAbort(); } setSignalHandler(); //向log檔案中寫入一些資料 dvmDumpLoaderStats("zygote"); //子進程被fork出來 pid = fork(); if (pid == 0) { //在這雷根據傳入的參數對子進程做出一些處理,例如設定進程名,設定各種id等 ...... } return pid;}
至此system_server進程終於被建立出來,我們可以看到system_server進程也是通過Linux系統特有的Fork機制分裂複製出來的。在fork之前,我們還有一個重要方法沒有分析–setSignalHandler方法,該方法用來設定訊號處理,下面讓我來看一下吧。
static void setSignalHandler(){ int err; struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = sigchldHandler; err = sigaction (SIGCHLD, &sa, NULL);//設定訊號處理函數,該訊號是子進程死亡的訊號 if (err < 0) { ALOGW("Error setting SIGCHLD handler: %s", strerror(errno)); }}static void sigchldHandler(int s){ pid_t pid; int status; while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { /* 列印出我們所關心的進程的死亡狀態. */ ...... /* * 如果剛剛銷毀的進程是system_server, 同時殺死zygote進程 * 這樣system_server進程和zygote進程將會被init進程重啟 */ if (pid == gDvm.systemServerPid) { ALOG(LOG_INFO, ZYGOTE_LOG_TAG, "Exit zygote because system server (%d) has terminated", (int) pid); kill(getpid(), SIGKILL); } } if (pid < 0) { ALOG(LOG_WARN, ZYGOTE_LOG_TAG, "Zygote SIGCHLD error in waitpid: %s",strerror(errno)); }}
這裡我們發現我們之前已經看到在forkSystemServer方法中已經檢查過system_server進程是否死亡,為什麼這裡還要再一次進行檢查?這是為了防止在我們還沒有得到fork子進程的pid時,system_server進程就已經死亡的情況。
總結一下:system_server進程的建立經曆了漫長的曆程:首先startSystemServer中調用了native方法forkSystemServer;之後在native方法forkSystemServer中調用了forkAndSpecializeCommon方法;在forkAndSpecializeCommon方法中fork之前還調用了setSignalHandler來設定訊號處理項。這樣,我們的system_server進程終於被建立起來,同時他還和zygote進程保持著同生共死的關係。
system_server進程的職責
在startSystemServer的方法中我們可以看到,在建立進程之後,在子進程即system_server進程中會執行handleSystemServerProcess方法,這便是system_server的職責所在,下面我們來看一下:
private static void handleSystemServerProcess( ZygoteConnection.Arguments parsedArgs) throws ZygoteInit.MethodAndArgsCaller { closeServerSocket(); // 設定許可權. Libcore.os.umask(S_IRWXG | S_IRWXO); ...... if (parsedArgs.invokeWith != null) { ...... } else { /* 剩餘的參數傳遞到SystemServer. */ RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs); } }
可以看到最後system_server進程來到了RuntimeInit中,它的實現在frameworks\base\core\java\com\android\internal\os\RuntimeInit.java中
public static final void zygoteInit(int targetSdkVersion, String[] argv) throws ZygoteInit.MethodAndArgsCaller { if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote"); //關閉System.out和System.err,使用Android log redirectLogStreams(); //做一些常規初始化 commonInit(); //native層初始化,調用此方法之後system_server將與Binder通訊系統建立聯絡,這樣就可以使用Binder了 nativeZygoteInit(); applicationInit(targetSdkVersion, argv); } private static void applicationInit(int targetSdkVersion, String[] argv) throws ZygoteInit.MethodAndArgsCaller { ...... try { args = new Arguments(argv); } catch (IllegalArgumentException ex) { Slog.e(TAG, ex.getMessage()); // let the process exit return; } invokeStaticMain(args.startClass, args.startArgs); }
可以看到,最終我們調用了invokeStaticMain方法,該方法的傳入參數在startSystemServer方法中被設定,其傳入參數的類名是”com.android.server.SystemServer”
private static void invokeStaticMain(String className, String[] argv) throws ZygoteInit.MethodAndArgsCaller { Class<?> cl; try { cl = Class.forName(className); } catch (ClassNotFoundException ex) { throw new RuntimeException( "Missing class when invoking static main " + className, ex); } Method m; try { 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); } /* 拋出的異常在ZygoteInit.main()中被截獲 */ throw new ZygoteInit.MethodAndArgsCaller(m, argv); }
讓我們來看看被截獲的語句:
catch (MethodAndArgsCaller caller) { caller.run();//調用了caller的run方法 }
run方法代碼:
public void run() { try { 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); } }
可以看到,在函數最後拋出異常,在ZygoteInit.main()中被截獲,由於傳遞的參數類名是”com.android.server.SystemServer”,這樣我們調用了MethodAndArgsCaller.run()方法去執行了SystemServer類的靜態main方法。(關於ZygoteInit可以參考上一篇博文:Android源碼分析–Zygote進程分析)
public static void main(String[] args) { ...... // Mmmmmm... more memory! dalvik.system.VMRuntime.getRuntime().clearGrowthLimit(); // system server一直在運行, 所以他需要儘可能有效利用記憶體 VMRuntime.getRuntime().setTargetHeapUtilization(0.8f); Environment.setUserRequired(true); System.loadLibrary("android_servers"); Slog.i(TAG, "Entered the Android system server!"); // native方法,進行一些感應器服務的初始化 nativeInit(); // 建立一個單獨的線程,在這裡啟動系統的各項服務 ServerThread thr = new ServerThread(); thr.initAndLoop(); }
最終,system_server開啟了一個新的線程,並執行了它的initAndLoop方法,其也被定義在SystemServer.java中,該方法的代碼較多,其主要的工作就是開啟了系統中的各項服務,如電池服務,藍芽服務等等。並調用了Looper的prepareMainLooper方法進行訊息迴圈,然後處理訊息,這裡不再贅述。
最後,我們來總結一下:
- 首先system_server執行handleSystemServerProcess方法來完成自己的使命;
- 之後調用RuntimeInit.zygoteInit方法,在這裡我們進行了一些常規的初始化工作已經native層的初始化,從而與Binder通訊建立聯絡;
- 之後調用invokeStaticMain方法,利用拋出異常的方法在ZygoteInit的main方法中截獲並去執行SystemServer的main方法;
- 在SystemServer的main方法中,我調用nativeInit方法去初始化一些感應器服務,並開啟了單獨的線程去開啟Android系統中的各項服務,並調用了Looper的prepareMainLooper方法進行訊息迴圈,然後處理訊息
Android源碼分析--system_server進程分析