前言
Android系統開發,zygote顯然是接觸很多的一個術語。那zygote是什麼呢?好奇查了下zygote的中文翻譯:受精卵。這是我見過最形象和最正確的命名。顧名思義,就是孵化下一代。Android中,Zygote是所有App的父進程,所有的app都由它孵化而出,可見zygote的地位,堪比女媧造人。那zygote在Android系統中是如何啓動的呢?
概述
衆所周知,Android系統是跑在Linux內核上的,姑且將zygote看成是跑在Linux上的一個Linux應用。那麼zygote想要啓動,則必然需要先讓Linux內核跑起來(聽起來像是廢話了~)。事實也是如此,zygote正是由Linux的天字第一號進程【init】啓動。接下來就是從init.rc開始,一路分析zygote的啓動過程。先上一張流程圖,本文所講的內容都在這。
init.rc
init進程啓動後,對init.rc文件進行了解析並執行了各個階段的動作,而zygote進程就是這個過程中被觸發啓動的。直接看代碼直觀點:
/system/core/rootdir/init.rc
on late-init
...
# Now we can start zygote for devices with file based encryption
trigger zygote-start
...
on zygote-start && property:ro.crypto.state=encrypted && property:ro.crypto.type=file
# A/B update verifier that marks a successful boot.
exec_start update_verifier_nonencrypted
start netd
start zygote
start zygote_secondary
...
zygote在init.rc中被觸發並通過【start zygote】的方式啓動,而這裏的zygote是init.rc文件中的服務,如下:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
writepid /dev/cpuset/foreground/tasks
可見zygote服務最終調用了app_process這個可執行文件,並傳入【–zygote】和【–start-system-server】這兩個參數。
app_main
app_main是一個可執行文件,入口是main函數,具體源碼如下:
/frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[])
{
...
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
...
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) { //傳參
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) { //傳參
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName.setTo(arg + 12);
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg);
break;
} else {
--i;
break;
}
}
...
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
}
...
}
專注zygote相關的關鍵代碼,在這個main函數中,主要做了三件事:
1.使用AppRuntime類實例化了一個虛擬機runtime,而AppRuntime則繼承AndroidRuntime;
2.解析傳給app_main的參數,主要是zygote和start_system_server;
3.啓動虛擬機。啓動的方法start是父類AndroidRuntime的方法。注意第一個傳參的參數。
zygote啓動方法在AndroidRuntime中,進入觀摩下。
AndroidRuntime
frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
...
JniInvocation jni_invocation;
jni_invocation.Init(NULL); //加載libart.so
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
onVmCreated(env);
/*
* Register android functions.
*/
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
...
char* slashClassName = toSlashClassName(className != NULL ? className : "");
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V");
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
}
...
}
start方法中,主要做了四件事:
1.加載libart.so,否則不能啓動虛擬機;
2.啓動虛擬機;
3.加載註冊JNI方法;
4.根據傳遞給start方法的第一個參數,去尋找ZygoteInit類,找到類之後,找到該類的main方法,然後調用,在這之後就進入了Java的世界。
start方法的第一個參數爲"com.android.internal.os.ZygoteInit",然後通過FindClass方法找到ZygoteInit類,然後再調用相應的main方法進入到Java世界。
ZygoteInit
到了這裏,就已經進入到了Java的世界,虛擬機已經運行起來,接下來要做的事就是啓動system_server,然後做好自己的本分,等待孵化app的指令。具體詳見main方法:
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
...
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) {
r.run();
return;
}
}
Log.i(TAG, "Accepting command socket connections");
// The select loop returns early in the child process after a fork and
// loops forever in the zygote.
caller = zygoteServer.runSelectLoop(abiList);
if (caller != null) {
caller.run();
}
...
}
主要做了三件事:
1.解析參數;
2.fork system_server;
3.調用runSelectLoop方法,等待進程孵化請求;
每個main方法一定會做的事情,那就是解析傳入給它的參數,這裏主要解析了start_system_server的創建需求,這個參數事從init.rc中傳下來的。如果init.rc中有創建的system_server的需求,那麼就會在這裏被解析,然後進行創建。zygote在完成了system_server的創建後,調用runSelectLoop方法進行等待,響應app進程的創建請求,創建成功後,再調用run方法執行。
結語
zygote的啓動分析到此結束,到了這裏,zygote就一直等待進程的創建請求,app想要啓動的時候,就由ams通過socket發需求給zygote就好。
每一次的源碼閱讀,都有種【自己很渺小】的感覺。對自己來講,對Android源碼的每一次閱讀,就是一次揭祕的過程。但每一次閱讀完,都會產生新的疑問,比如app的啓動流程是怎麼樣的?ams又是跟zygote怎樣創建聯繫的?
但正是這些疑問驅使我去閱讀源碼,去了解箇中奧妙。
最後
我在微信公衆號也有寫文章,更新比較及時,有興趣者可以掃描如下二維碼,或者微信搜索【Android系統實戰開發】,關注有驚喜哦!