Android4.4的zygote程序(下)
3.2.4啟動Android系統服務——startSystemServer()
接下來就是啟動Android的重頭戲了,此時ZygoteInit的main()函式會呼叫startSystemServer(),該函式用於啟動整個Android系統的系統服務。其大體做法是先fork一個子程序,然後在子程序中做一些初始化動作,繼而執行SystemServer類的main()靜態函式。需要注意的是,startSystemServer()並不是在函式體內直接呼叫Java類的main()函式的,而是通過拋異常的方式,在startSystemServer()之外加以處理的。
startSystemServer()的程式碼如下:
private static boolean startSystemServer() throws MethodAndArgsCaller, RuntimeException { . . . . . . /* Hardcoded command line to start the system server */ 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", "--capabilities=" + capabilities + "," + capabilities, "--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); // fork出系統服務對應的程序 pid = Zygote.forkSystemServer(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } // 對新fork出的系統程序,執行handleSystemServerProcess() if (pid == 0) { handleSystemServerProcess(parsedArgs); } return true; }
args[]中的字串 | 對應 |
"--setuid=1000" | parsedArgs.uid |
"--setgid=1000" | parsedArgs.gid |
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008, |
parsedArgs.gids |
"--capabilities=" + capabilities + "," + capabilities | capabilitiesSpecified = true; permittedCapabilities = Long.decode(capStrings[0]); effectiveCapabilites = Long.decode(capString[1]); |
"--runtime-init" | parsedArgs.runtimeInit設為true |
"--nice-name=system_server" | parsedArgs.niceName |
"com.android.server.SystemServer" | parsedArgs.remainingArgs |
3.2.4.1Zygote.forkSystemServer()
Zygote.forkSystemServer()的程式碼如下:
【libcore/dalvik/src/main/java/dalvik/system/Zygote.java】
public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities)
{
preFork();
int pid = nativeForkSystemServer(uid, gid, gids, debugFlags, rlimits,
permittedCapabilities, effectiveCapabilities);
postFork();
return pid;
}
其中的nativeForkSystemServer()是個native成員函式,其對應的C++層函式為Dalvik_dalvik_system_Zygote_forkSystemServer()。
【dalvik/vm/native/dalvik_system_Zygote.cpp】
const DalvikNativeMethod dvm_dalvik_system_Zygote[] = {
{ "nativeFork", "()I",
Dalvik_dalvik_system_Zygote_fork },
{ "nativeForkAndSpecialize", "(II[II[[IILjava/lang/String;Ljava/lang/String;)I",
Dalvik_dalvik_system_Zygote_forkAndSpecialize },
{ "nativeForkSystemServer", "(II[II[[IJJ)I",
Dalvik_dalvik_system_Zygote_forkSystemServer },
{ NULL, NULL, NULL },
};
static void Dalvik_dalvik_system_Zygote_forkSystemServer(
const u4* args, JValue* pResult)
{
pid_t pid;
pid = forkAndSpecializeCommon(args, true);
if (pid > 0) {
int status;
ALOGI("System server process %d has been created", pid);
gDvm.systemServerPid = pid;
if (waitpid(pid, &status, WNOHANG) == pid) {
ALOGE("System server process %d has died. Restarting Zygote!", pid);
kill(getpid(), SIGKILL);
}
}
RETURN_INT(pid);
}
forkAndSpecializeCommon()內部其實會呼叫fork(),而後設定gid、uid等資訊。
3.2.4.2SystemServer的handleSystemServerProgress()函式
接著,startSystemServer()會在新fork出的子程序中呼叫handleSystemServerProgress(),讓這個新程序成為真正的系統程序(SystemServer程序)。
// 對新fork出的系統程序,執行handleSystemServerProcess()
if (pid == 0) {
handleSystemServerProcess(parsedArgs);
}
注意,呼叫handleSystemServerProcess()時,程式是執行在新fork出的程序中的。handleSystemServerProcess()的程式碼如下:
【frameworks/base/core/java/com/android/internal/os/ZygoteInit.java】
private static void handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller
{
closeServerSocket();
Libcore.os.umask(S_IRWXG | S_IRWXO);
if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName); // niceName就是”system_server”
}
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
null, parsedArgs.remainingArgs);
} else {
// 此時的remainingArgs就是”com.android.server.SystemServer”
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs);
}
}
3.2.4.2.1closeServerSocket()
因為當前已經不是執行在zygote程序裡了,所以zygote裡的那個監聽socket就應該關閉了。這就是closeServerSocket()的意義,其程式碼如下:
static void closeServerSocket()
{
try {
if (sServerSocket != null) {
FileDescriptor fd = sServerSocket.getFileDescriptor();
sServerSocket.close();
if (fd != null) {
Libcore.os.close(fd);
}
}
} catch (IOException ex) {
Log.e(TAG, "Zygote: error closing sockets", ex);
} catch (libcore.io.ErrnoException ex) {
Log.e(TAG, "Zygote: error closing descriptor", ex);
}
sServerSocket = null;
}
在handleSystemServerProcess()函式裡,parsedArgs.niceName就是“system_server”,而且因為parsedArgs.invokeWith沒有指定,所以其值為null,於是程式會走到RuntimeInit.zygoteInit()。
3.2.4.2.2RuntimeInit.zygoteInit()
RuntimeInit.zygoteInit()的程式碼如下:
【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");
redirectLogStreams();
commonInit();
nativeZygoteInit();
applicationInit(targetSdkVersion, argv);
}
3.2.4.2.2.1.呼叫redirectLogStreams()
首先,在新fork出的系統程序裡,需要重新定向系統輸出流。
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"));
}
3.2.4.2.2.2.呼叫commonInit()
private static final void commonInit()
{
. . . . . .
Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());
TimezoneGetter.setInstance(new TimezoneGetter()
. . . . . .
. . . . . .
String trace = SystemProperties.get("ro.kernel.android.tracing");
. . . . . .
initialized = true;
}
當前正處於系統程序的主執行緒中,可以呼叫Thread.setDefaultUncaughtExceptionHandler()來設定一個預設的異常處理器,處理程式中的未捕獲異常。其他的初始化動作,我們暫不深究。
3.2.4.2.2.3.呼叫nativeZygoteInit()
接下來呼叫的nativeZygoteInit()是個JNI函式,在AndroidRuntime.cpp檔案中可以看到:
【frameworks/base/core/jni/AndroidRuntime.cpp】
static JNINativeMethod gMethods[] = {
{ "nativeFinishInit", "()V",
(void*) com_android_internal_os_RuntimeInit_nativeFinishInit },
{ "nativeZygoteInit", "()V",
(void*) com_android_internal_os_RuntimeInit_nativeZygoteInit },
{ "nativeSetExitWithoutCleanup", "(Z)V",
(void*) com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup },
};
nativeZygoteInit()對應的本地函式為com_android_internal_os_RuntimeInit_nativeZygoteInit()。
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}
gCurRuntime是C++層的AndroidRuntime類的靜態變數。在AndroidRuntime構造之時,
gCurRuntime = this。不過實際呼叫的onZygoteInit()應該是AndroidRuntime的子類AppRuntime的:
【frameworks/base/cmds/app_process/App_main.cpp】
class AppRuntime : public AndroidRuntime
{
. . . . . .
virtual void onZygoteInit()
{
// Re-enable tracing now that we're no longer in Zygote.
atrace_set_tracing_enabled(true);
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
裡面構造了程序的ProcessState全域性物件,而且啟動了執行緒池。
ProcessState物件是典型的單例模式,它的self()函式如下:
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
return gProcess;
}
gProcess = new ProcessState;
return gProcess;
}
ProcessState對於Binder通訊機制而言非常重要,現在system server程序的PrecessState算是初始化完畢了。
我們整理一下思路,畫一張startSystemServer()的呼叫關係圖:
接下來我們來講上圖中zygoteInit()呼叫的最後一行:applicationInit()。
3.2.4.2.2.4.呼叫applicationInit()
applicationInit()函式的程式碼如下:
【frameworks/base/core/java/com/android/internal/os/RuntimeInit.java】
private static void applicationInit(int targetSdkVersion, String[] argv)
throws ZygoteInit.MethodAndArgsCaller
{
nativeSetExitWithoutCleanup(true);
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
final Arguments args;
try {
args = new Arguments(argv);
} catch (IllegalArgumentException ex) {
Slog.e(TAG, ex.getMessage());
return;
}
invokeStaticMain(args.startClass, args.startArgs);
}
其中的invokeStaticMain()一句最為關鍵,它承擔向外丟擲“特殊異常”的作用。我們先畫一張startSystemServer()的呼叫關係圖:
看到了吧,最後一步丟擲了異常。這相當於一個“特殊的goto語句”!上面的cl = Class.forName(className)一句,其實載入的就是SystemServer類。這個類名是從前文的parsedArgs.remainingArgs得來的,其值就是“com.android.server.SystemServer”。此處丟擲的異常,會被本程序的catch語句接住,在那裡才會執行SystemServer類的main()函式。示意圖如下:
如上圖所示,新fork出的SystemServer子程序直接跳過了中間那句runSelectLoop(),徑直跳轉到caller.run()一步了。
當然,父程序Zygote在fork動作後,會退出startSystemServer()函式,並走到runSelectLoop(),從而進入一種迴圈監聽狀態,每當Activity Manager Service向它發出“啟動新應用程序”的命令時,它又會fork一個子程序,並在子程序裡丟擲一個異常,這樣子程序還是會跳轉到catch一句。
我們可以把上面的示意圖再豐富一下:
還有一點需要說明一下,fork出的SystemServer程序在跳轉到catch語句後,會執行SystemServer類的main()函式,而其他情況下,fork出的應用程序在跳轉的catch語句後,則會執行ActivityThread類的main()函式。這個ActivityThread對於應用程式而言非常重要,但因為和本篇主題關係不大,我們就不在這裡展開講了。
3.2.4.3 SystemServer的main()函式
前文我們已經看到了,startSystemServer()建立的新程序在執行完applicationInit()之後,會丟擲一個異常,並由新fork出的SystemServer子程序的catch語句接住,繼而執行SystemServer類的main()函式。
那麼SystemServer的main()函式又在做什麼事情呢?其呼叫關係圖如下:
在Android4.4版本中,ServerThread已經不再繼承於Thread了,它現在只是個輔助類,其命名還殘留有舊程式碼的味道。在以前的Android版本中,ServerThread的確繼承於Thread,而且線上程的run()成員函式裡,做著類似addService、systemReady的工作。
因為本文主要是闡述zygote程序的,所以我們就不在這裡繼續細說system server程序啦,有興趣的同學可以繼續研究。我們還是回過頭繼續說zygote裡的動作吧。
3.2.5監聽zygote socket
3.2.5.1runSelectLoop()
ZygoteInit的main()函式在呼叫完startSystemServer()之後,會進一步走到runSelectLoop()。runSelectInit()的程式碼如下:
【frameworks/base/core/java/com/android/internal/os/ZygoteInit.java】
private static void runSelectLoop() throws MethodAndArgsCaller
{
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
FileDescriptor[] fdArray = new FileDescriptor[4];
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
int loopCount = GC_LOOP_COUNT;
while (true) {
int index;
if (loopCount <= 0) {
gc();
loopCount = GC_LOOP_COUNT;
} else {
loopCount--;
}
try {
fdArray = fds.toArray(fdArray);
index = selectReadable(fdArray);
} catch (IOException ex) {
throw new RuntimeException("Error in select()", ex);
}
if (index < 0) {
throw new RuntimeException("Error in select()");
} else if (index == 0) {
ZygoteConnection newPeer = acceptCommandPeer();
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
boolean done;
done = peers.get(index).runOnce();
if (done) {
peers.remove(index);
fds.remove(index);
}
}
}
}
在一個while迴圈中,不斷呼叫selectReadable()。該函式是個native函式,對應C++層的com_android_internal_os_ZygoteInit_selectReadable()。
【frameworks/base/core/jni/com_android_internal_os_ZygoteInit.cpp】
static jint com_android_internal_os_ZygoteInit_selectReadable (JNIEnv *env, jobject clazz,
jobjectArray fds)
{
. . . . . .
int err;
do {
err = select (nfds, &fdset, NULL, NULL, NULL);
} while (err < 0 && errno == EINTR);
. . . . . .
for (jsize i = 0; i < length; i++) {
jobject fdObj = env->GetObjectArrayElement(fds, i);
. . . . . .
int fd = jniGetFDFromFileDescriptor(env, fdObj);
. . . . . .
if (FD_ISSET(fd, &fdset)) {
return (jint)i;
}
}
return -1;
}
可以看到,主要就是呼叫select()而已。在Linux的socket程式設計中,select()負責監視若干檔案描述符的變化情況,我們常見的變化情況有:讀、寫、異常等等。在zygote中,
err = select (nfds, &fdset, NULL, NULL, NULL);一句的最後三個引數都為NULL,表示該select()操作只打算監視檔案描述符的“讀變化”,而且如果沒有可讀的檔案,select()就維持阻塞狀態。
在被監視的檔案描述符陣列(fds)中,第一個檔案描述符對應著“zygote接收其他程序連線申請的那個socket(及sServerSocket)”,一旦它發生了變化,我們就嘗試建立一個ZygoteConnection。
// (index == 0)的情況
ZygoteConnection newPeer = acceptCommandPeer();
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
看到了嗎,新建立的ZygoteConnection會被再次寫入檔案描述符陣列(fds)。
如果select動作發現檔案描述符陣列(fds)的其他檔案描述符有東西可讀了,說明有其他程序通過某個已建立好的ZygoteConnection發來了命令,此時我們需要呼叫runOnce()。
// (index > 0)的情況
boolean done;
done = peers.get(index).runOnce();
if (done) {
peers.remove(index);
fds.remove(index);
}
建立ZygoteConnection的acceptCommandPeer()的程式碼如下:
private static ZygoteConnection acceptCommandPeer() {
try {
return new ZygoteConnection(sServerSocket.accept());
} catch (IOException ex) {
throw new RuntimeException(
"IOException during accept()", ex);
}
}
3.2.5.1.1ZygoteConnection的runOnce()
ZygoteConnection的runOnce()程式碼截選如下:
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
String args[];
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
. . . . . .
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
. . . . . .
int pid = -1;
FileDescriptor childPipeFd = null;
FileDescriptor serverPipeFd = null;
try {
parsedArgs = new Arguments(args);
. . . . . .
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal,
parsedArgs.seInfo, parsedArgs.niceName);
}
. . . . . .
if (pid == 0) {
// in child
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
return true;
} else {
// in parent...pid of < 0 means failure
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
}
. . . . . .
}
3.2.5.1.2readArgumentList()
runOnce()中從socket中讀取引數資料的動作是由readArgumentList()完成的,該函式的程式碼如下:
private String[] readArgumentList()
throws IOException
{
int argc;
. . . . . .
String s = mSocketReader.readLine();
. . . . . .
argc = Integer.parseInt(s);
. . . . . .
String[] result = new String[argc];
for (int i = 0; i < argc; i++) {
result[i] = mSocketReader.readLine();
if (result[i] == null) {
// We got an unexpected EOF.
throw new IOException("truncated request");
}
}
return result;
}
可是是誰在向這個socket寫入引數的呢?當然是AMS啦。
我們知道,當AMS需要啟動一個新程序時,會呼叫類似下面的句子:
Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, null);
包括ActivityThread類名等重要資訊的引數,最終就會通過socket傳遞給zygote。
3.2.5.1.3handleChildProc()
runOnce()在讀完引數之後,會進一步呼叫到handleChildProc()。正如前文所說,該函式會間接丟擲特殊的MethodAndArgsCaller異常,只不過此時丟擲的異常攜帶的類名為ActivityThread。
private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors,
FileDescriptor pipeFd, PrintStream newStderr)
throws ZygoteInit.MethodAndArgsCaller
{
closeSocket();
ZygoteInit.closeServerSocket();
. . . . . .
if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName);
}
if (parsedArgs.runtimeInit) {
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
pipeFd, parsedArgs.remainingArgs);
} else {
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs);
}
} else {
String className;
. . . . . .
className = parsedArgs.remainingArgs[0];
. . . . . .
String[] mainArgs = new String[parsedArgs.remainingArgs.length - 1];
System.arraycopy(parsedArgs.remainingArgs, 1,
mainArgs, 0, mainArgs.length);
if (parsedArgs.invokeWith != null) {
WrapperInit.execStandalone(parsedArgs.invokeWith,
parsedArgs.classpath, className, mainArgs);
} else {
ClassLoader cloader;
if (parsedArgs.classpath != null) {
cloader = new PathClassLoader(parsedArgs.classpath,
ClassLoader.getSystemClassLoader());
} else {
cloader = ClassLoader.getSystemClassLoader();
}
try {
ZygoteInit.invokeStaticMain(cloader, className, mainArgs);
} catch (RuntimeException ex) {
logAndPrintError(newStderr, "Error starting.", ex);
}
}
}
}
4小結
至此,zygote程序就闡述完畢了。作為一個最原始的“受精卵”,它必須在合適的時機進行必要的細胞分裂。分裂動作也沒什麼大的花樣,不過就是fork()新程序而已。如果fork()出的新程序是system server,那麼其最終執行的就是SystemServer類的main()函式,而如果fork()出的新程序是普通的使用者程序的話,那麼其最終執行的就是ActivityThread類的main()函式。有關ActivityThread的細節,我們有時間再深入探討,這裡就不細說了。
本篇文章和我的上一篇文章《Android4.4的init程序》可以算是姊妹篇啦。讀完這兩篇文章,我相信大家對Android的啟動流程能有一些大面上的認識了。