Zygote进程是Android系统中第一个Java进程,由init进程启动的时候创建。
在Android系统中,虚拟机(DVM、ATR),应用程序进程以及系统关键服务SystemServer进程都是由Zygote进程来创建的,它通过fork的形式(复制进程)来创建应用程序和SystemServer进程,由于Zygote进程在启动的时候会创建DVM或者ART虚拟机,因此通过fork而创建的应用程序和SystemServer进程可以在内部获取DVM或者ART的实例副本。
最开始Zygote进程名称为"app_process",在Andorid.bp文件中定义的,后来进程启动后,名称才换成的"zygote":
@frameworks/base/cmds/app_process/Android.bp
cc_binary {
name: "app_process",
srcs: ["app_main.cpp"],
multilib: {
lib32: {
suffix: "32",
},
lib64: {
suffix: "64",
},
},
...
}
Zygote启动脚本
Zygote启动脚本都放在system/core/rootdir/目录下,由import 语句将init.${ro.zygote}.rc文件引入init.rc文件中:
@system/core/rootdir/init.rc
import /system/etc/init/hw/init.${ro.zygote}.rc
init.rc根据ro.zygote的值来引入不同的文件:
- init.zygote32.rc
- init.zygote64.rc
- init.zygote64_32.rc
位于init.${ro.zygote}.rc文件中的启动脚本定义:
@system/core/rootdir/init.zygote64.rc
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
//1
class main
...
注释1定义zygote服务为main类型服务,系统在合适的时候会统一启动main类型的的服务:
@system/core/rootdir/init.rc
on nonencrypted
class_start main
class_start late_start
在init.rc文件中Action语句on nonencrypted触发class_start mainCommand语句,执行do_class_start函数,最终走到system/core/init/service.cpp#Start函数中去启动zygote服务:Android14 - init进程的启动过程这篇文章
@system/core/init/service.cpp#Start
Result<void> Service::Start() {
...
//如果service已经在运行了,就不启动了
if (flags_ & SVC_RUNNING) {
if ((flags_ & SVC_ONESHOT) && disabled) {
flags_ |= SVC_RESTART;
}
LOG(INFO) << "service '" << name_
<< "' requested start, but it is already running (flags: " << flags_ << ")";
// It is not an error to try to start a service that is already running.
reboot_on_failure.Disable();
return {};
}
...
//判断需要启动的service对应的执行文件是否存在,不存在则不启动
struct stat sb;
if (stat(args_[0].c_str(), &sb) == -1) {
flags_ |= SVC_DISABLED;
return ErrnoError() << "Cannot find '" << args_[0] << "'";
}
...
//根据参数创建子进程
pid_t pid = -1;
if (namespaces_.flags) {
pid = clone(nullptr, nullptr, namespaces_.flags | SIGCHLD, nullptr);
} else {
pid = fork();
}
//当前代码逻辑在子进程中运行
if (pid == 0) {
umask(077);
cgroups_activated.CloseWriteFd();
setsid_finished.CloseReadFd();
//最终执行execv函数,Service子进程被启动
RunService(descriptors, std::move(cgroups_activated), std::move(setsid_finished));
_exit(127);
} else {
cgroups_activated.CloseReadFd();
setsid_finished.CloseWriteFd();
}
if (pid < 0) {
pid_ = 0;
return ErrnoError() << "Failed to fork";
}
...
return {};
}
Zygote启动过程
Zygote进程在init进程中通过fork函数创建而来:
fork函数
fork函数的被调用一次,可以返回两次结果,其返回值分为三种类型:
- 如果出现错误,fork函数返回一个负数;
- fork操作成功,当前代码所在进程为fork执行前的进程,返回值为子进程的进程ID;
- fork操作成功,当前代码所在进程为fork出来的子进程,返回值为0;
因此我们可以通过返回值来判断当前进程是子进程还是父进程。
相当于fork后,出现了一个与当前进程代码一样的新进程,两个进程fork返回的fpid值不一样,程序可以根据fpid为0时,即表示当前程序位于新创建的子进程中,去执行属于子进程的逻辑,比如初始化子进程的事务。
Zygote在Native层
因此在上文Service的start函数中,通过fork函数创建Zygote进程后,在子进程Zygote中调用RunService函数,最终通过execv函数进入Zygote进程的入口main函数中,位于frameworks/base/cmds/app_process/app_main.cpp中,执行后续的进程初始化操作:
@frameworks/base/cmds/app_process/app_main.cpp#main
int main(int argc, char* const argv[])
{
static const char ZYGOTE_NICE_NAME[] = "zygote64";
while (i < argc) {
const char* arg = argv[i++];
//1
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 (!niceName.isEmpty()) {
runtime.setArgv0(niceName.string(), true /* setProcName */);
}
if (zygote) {
//2
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (!className.isEmpty()) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
}
}
在zygote进程的启动脚本service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote中,有参数--zygote,因此在注释1处解析参数后,在注释2处通过runtime的start函数进入ZygoteInit的main方法:
@frameworks/base/core/jni/AndroidRuntime.cpp?#start
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
...
/* start the virtual machine */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
//启动、创建Java虚拟机
if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
return;
}
onVmCreated(env);
/*
*
* 为JVM虚拟机注册JNI方法
*/
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
/*
* We want to call main() with a String array with arguments in it.
* At present we have two arguments, the class name and an option string.
* Create an array to hold them.
*/
jclass stringClass;
jobjectArray strArray;
jstring classNameStr;
stringClass = env->FindClass("java/lang/String");
assert(stringClass != NULL);
strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
assert(strArray != NULL);
//根据前文可知此时className为com.android.internal.os.ZygoteInit
classNameStr = env->NewStringUTF(className);
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr);
for (size_t i = 0; i < options.size(); ++i) {
jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
assert(optionsStr != NULL);
env->SetObjectArrayElement(strArray, i + 1, optionsStr);
}
//将className中的"."替换为"/"
char* slashClassName = toSlashClassName(className != NULL ? className : "");
//找打ZygoteInit
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
//找到ZygoteInit的main方法
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 {
//通过JNI调用ZygoteInit的main方法
env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
}
}
在AndroidRuntime的start方法中,先创建启动Java虚拟机,然后为虚拟机注册JNI方法,最后因为此时位于Native层,通过JNI方法进入ZygoteInit的main方法。从此Zygote便进入了Java框架层,可以说Zygote开创了Java框架层。
Zygote在Java框架层
@frameworks/base/core/java/com/android/internal/os/ZygoteInit.java#main
public static void main(String[] argv) {
ZygoteServer zygoteServer = null;
...
Runnable caller;
try {
// Store now for StatsLogging later.
final long startTime = SystemClock.elapsedRealtime();
//读取系统是否启动完成
final boolean isRuntimeRestarted = "1".equals(
SystemProperties.get("sys.boot_completed"));
RuntimeInit.preForkInit();
boolean startSystemServer = false;
String zygoteSocketName = "zygote";
String abiList = null;
boolean enableLazyPreload = false;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
//从 AndroidRuntime.cpp 中传递上来,已经包含了 start-system-server
//此时startSystemServer为ture
startSystemServer = true;
}
...
}
final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);
...
if (!enableLazyPreload) {
//1.预加载类和资源
preload(bootTimingsTraceLog);
}
//2.实例化ZygoteServer,主要为了创建管理一个名为ANDROID_SOCKET_zygote的socket,用来等待AMS来请求Zygote来fork处新的应用进程。
//因此AMS里启动的应用程序,都是由该socket进行处理并fork出子进程的。
zygoteServer = new ZygoteServer(isPrimaryZygote);
//默认为ture,用于启动SystemServer
if (startSystemServer) {
//3. fork出SystemServer进程并启动
//在子进程中返回Runnable对象用于在SystemServer进程中去启动执行
//在父进程中返回null
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
if (r != null) {
//4. 表示当前代码逻辑在子进程SystemServer中,运行Runnable,里面主要是通过反射找到并进入SystemServer的main方法
r.run();
return;
}
}
//5. forkSystemServer返回null,进入zygoteServer的runSelectLoop开始while死循环,不断读取来自client端进程的请求(等待AMS的请求)
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with fatal exception", ex);
throw ex;
} finally {
//如果发生异常,关闭zygoteServer里面的socket
if (zygoteServer != null) {
zygoteServer.closeServerSocket();
}
}
...
}
注释1通过preload去预加载一些系统资源,包括类资源,文件资源,Graphics库等:
@frameworks/base/core/java/com/android/internal/os/ZygoteInit.java#preload
static void preload(TimingsTraceLog bootTimingsTraceLog) {
preloadClasses();
cacheNonBootClasspathClassLoaders();
preloadResources();
nativePreloadAppProcessHALs();
maybePreloadGraphicsDriver();
preloadSharedLibraries();
preloadTextResources();
...
sPreloadComplete = true;
}
注释2处构造ZygoteServer对象,在其构造方法中创建了名为ANDROID_SOCKET_zygote的socket:
@frameworks/base/core/java/com/android/internal/os/ZygoteServer.java#ZygoteServer
ZygoteServer(boolean isPrimaryZygote) {
mUsapPoolEventFD = Zygote.getUsapPoolEventFD();
//创建socket
if (isPrimaryZygote) {
mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME);
...
}
...
}
注释3fork出SystemServer进程并启动,注释4主要是在SyetemServer进程进入frameworks/base/services/java/com/android/server/SystemServer.java:main()方法执行SystemServer的后续操作。注释5主要是为了让zygoteServer中的zygotesocket循环运行,等待client进程的请求后创建子进程(比如等待AMS的请求)。
Zygote进程在Java框架层主要做了3件事:
- 预加载类和资源
- 创建socket,等待其他进程的请求后创建新的应用程序进程
- 启动SystemServer进程
总结
Zygote进程自init进程创建,主要做了以下几件事:
- 创建Java虚拟机并为Java虚拟机注册JNI方法。
- 通过JNI调用ZygoteInit的main方法,标识这Zygote从Native层进入Java框架层。
- 预加载类和资源
- 创建服务端socket,等待其他client端请求后创建新的应用程序进程。
- 启动SystemServer进程。