概述
zygote是android 系统的一个孵化器,可通过它分裂一个个子进程,为了理解zygote工作原理,这里做些记录,方便后续查阅和修正,加深理解。
基于andoid 4.4阅读
init启动zygote
init作为linux 用户空间第一个进程,主要目的是通过解析init.rc来启动android一系列的进程服务。其中就有zygote
关于解析规则可参考源码system/core/init/readme.txt
zygote的启动配置
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class core
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
参考用例:
服务是初始化启动和(可选)重新启动的程序,当他们退出时。 服务采取以下形式:
service <name> <pathname> [ <argument> ]*
<option>
<option>
...
name : 进程的名字zygote
pathname:执行文件路径 /system/bin/app_process
argument: 执行的参数 -Xzygote /system/bin --zygote --start-system-server
zygote程序入口
/system/bin/app_process的进程编译文件路径:frameworks/base/cmds/app_process/app_main.cpp
通过上面init.rc的配置我们知道argv参数有
-Xzygote
/system/bin
–zygote
–start-system-server
int main(int argc, char* const argv[])
{
// These are global variables in ProcessState.cpp
mArgC = argc;
mArgV = argv;
mArgLen = 0;
for (int i=0; i<argc; i++) {
mArgLen += strlen(argv[i]) + 1;
}
mArgLen--;
AppRuntime runtime;
const char* argv0 = argv[0];
// Process command line arguments
// ignore argv[0]
argc--;
argv++;
// Everything up to '--' or first non '-' arg goes to the vm
int i = runtime.addVmArguments(argc, argv);
// Parse runtime arguments. Stop at first unrecognized option.
bool zygote = false;
bool startSystemServer = false;
bool application = false;
const char* parentDir = NULL;
const char* niceName = NULL;
const char* className = NULL;
while (i < argc) {
const char* arg = argv[i++];
if (!parentDir) {
parentDir = arg;
} else if (strcmp(arg, "--zygote") == 0) {//满足条件
zygote = true;
niceName = "zygote";
} 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 = arg + 12;
} else {
className = arg;
break;
}
}
//待循环获取参数后
//zygote = true; niceName = "zygote";startSystemServer = true;
if (niceName && *niceName) {
setArgv0(argv0, niceName);
set_process_name(niceName);
}
runtime.mParentDir = parentDir;
if (zygote) {
//会通过AndrodRuntime.start 反射启动java类ZygoteInit的
//静态方法main并带参数 start-system-server
runtime.start("com.android.internal.os.ZygoteInit",
startSystemServer ? "start-system-server" : "");
} else if (className) {
// Remainder of args get passed to startup class main()
runtime.mClassName = className;
runtime.mArgC = argc - i;
runtime.mArgV = argv + i;
runtime.start("com.android.internal.os.RuntimeInit",
application ? "application" : "tool");
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
return 10;
}
}
具体start过程可以查看拿AndroidRuntime.cpp
/ *
*启动Android运行时。 这涉及启动虚拟机并在" className"命名的类中
*调用" static void main(String [] args)"方法。
*
*向主函数传递两个参数,即类名和指定的选项字符串。
* /
void AndroidRuntime::start(const char* className, const char* options)
{
ALOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n",
className != NULL ? className : "(unknown)");
//'startSystemServer == true'表示运行时已过时,不再从init.rc中运行,
//因此我们在此处打印启动启动事件。
if (strcmp(options, "start-system-server") == 0) {//满足条件
/*在启动顺序中跟踪我们的进度 */
const int LOG_BOOT_PROGRESS_START = 3000;
LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START,
ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
}
const char* rootDir = getenv("ANDROID_ROOT");
if (rootDir == NULL) {
rootDir = "/system";
if (!hasDir("/system")) {
LOG_FATAL("No root directory specified, and /android does not exist.");
return;
}
setenv("ANDROID_ROOT", rootDir, 1);
}
//const char* kernelHack = getenv("LD_ASSUME_KERNEL");
//ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
/* 启动虚拟机 */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env) != 0) {
return;
}
onVmCreated(env);
/*
* 注册android函数。
*/
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
/ *
*我们想用包含参数的String数组调用main()。
*目前,我们有两个参数,即类名和选项字符串。
*创建一个数组来保存它们。
* /
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
jstring optionsStr;
stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
strArray = env->NewObjectArray(2, stringClass, NULL);
assert(strArray != NULL);
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr);
optionsStr = env->NewStringUTF(options);
env->SetObjectArrayElement(strArray, 1, optionsStr);
/ *
*启动VM。 该线程成为VM的主线程,并将
*在虚拟机退出之前不返回。
* /
char* slashClassName = toSlashClassName(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 {
//反射的方式静态启动main方法
env->CallStaticVoidMethod(startClass, startMeth, strArray);
#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
free(slashClassName);
ALOGD("Shutting down VM\n");
if (mJavaVM->DetachCurrentThread() != JNI_OK)
ALOGW("Warning: unable to detach main thread\n");
if (mJavaVM->DestroyJavaVM() != 0)
ALOGW("Warning: VM did not shut down cleanly\n");
}
启动后会在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
main运行
public static void main(String argv[]) {
try {
// 开始分析zygote初始化。
SamplingProfilerIntegration.start();
registerZygoteSocket();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
//预加载资源和类
preload();
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
// 完成概要分析zygote初始化。
SamplingProfilerIntegration.writeZygoteSnapshot();
// 启动后进行初始gc清理
gc();
// 禁用跟踪,以便分叉进程不会从Zygote继承陈旧的跟踪标记。
Trace.setTracingEnabled(false);
// 如果需要,请直接从Zygote启动系统服务器
if (argv.length != 2) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
if (argv[1].equals("start-system-server")) {
startSystemServer();
} else if (!argv[1].equals("")) {
throw new RuntimeException(argv[0] + USAGE_STRING);
}
Log.i(TAG, "Accepting command socket connections");
//运行循环读取socket信息,用于fork分裂子进程
runSelectLoop();
closeServerSocket();
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}
此时zygote已经启动完毕,后续是systemserver启动,在startSystemServer这个函数中通知启动android 的一系列系统服务。
zygote启动应用
时序图
- 从左边开始init启动,在通过解析init.rc 启动zygote;
- zygote内部初始化完毕后,启动systemserver,也是通过socket 通讯发送给zygote,解析后fork一个子进程,在启动SystemServer.main
- 在systemserver中会初始化ActivityManagerService,然后等systemReady 所有服务启动完成,便会用socket 通知zygote fork一个launcher app
- 在launcher 点击一个应用会使用startActivity启动一个app,也会同样通知zygote fork一个app