Zygote进程的发动流程
这道题想调查什么?
这道题想调查同学对Zygote进程的了解。
考生应该如何回答
zygote进程是由init进程发动的,init进程经过解读init.rc文件的办法发动了zygote,可是zygote所涉及的内容十分多,咱们需求一步一步的剖析它的细节。
1.Zygote是什么
Zygote是孵化器,在init进程发动时创立的,Zygote经过fork(仿制进程)的办法创立android中简直一切的使用程序进程和SystemServer进程。另外在Zygote进程发动的时候会创立DVM或许ART虚拟机,因此运用fork而树立的使用程序进程和SystemServer进程可以在内部得到一个DVM或许ART的实例副本,这样就保障了每个app进程在Zygote fork的那一刻就有了虚拟机。
2.Zygote发动脚本
init.rc文件中选用了如下所示的Import类型句子来导入Zygote发动脚本:import /init.${ro.zygote}.rc
这儿依据特点ro.zygote的内容来导入不同的Zygote发动脚本。从Android 5.0开端,Android开端支撑64位程序,Zygote有了32/64位之别,ro.zygote特点的取值有4种:
- init.zygote32.rc
- init.zygote64.rc
- init.zygote64_32.rc
注意:在system/core/rootdir目录中存放上面的Zygote的发动脚本。
上述脚本文件中的部分代码如下:
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
意思便是,履行 app_process64,该程序的途径是 /system/bin/app_process64
,类名是 main,进程名为 zygote。
3.Zygote进程发动流程
1.上述init脚本实践履行的是 /frameworks/base/cmds/app_process/app_main.cpp
中的 main 办法。
2.发动 zygote 进程在main 办法中会履行。
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
3.runtime.start
实践履行的是 /frameworks/base/core/jni/AndroidRuntime.cpp
的 start 办法
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
// 1.发动 java 虚拟机
if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
return;
}
onVmCreated(env);
// 2.为Java虚拟机注册JNI办法
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
// 3.classNameStr是传入的参数,值为com.android.internall.os.ZygoteInit
classNameStr = env->NewStringUTF(className);
// 4.运用toSlashClassName函数将className的 "." 替换为 "/",得到 com/android/internal/os/ZygoteInit
char* slashClassName = toSlashClassName(className != NULL ? className : "");
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
} else {
// 5.找到 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);
} else {
// 6.运用JNI调用ZygoteInit的main函数
env->CallStaticVoidMethod(startClass, startMeth, strArray);
}
}
}
经过上面的代码咱们不难发现,Zygote在发动进程中分别做了以下几件事:1)发动java虚拟机;2)注册android SDK需求运用的JNI办法;3)履行ZygoteInit的main函数,进而发动zygote的java层代码,终究Zygote就从Native层进入了Java FrameWork层。
特别说明
发动java虚拟机和 注册JNI的进程是zygote进程存在的一个十分关键的原因。正是由于zygote做了这样的事,因此它被用来fork其他进程。
到目前为止,并没有任何代码进入Java FrameWork层面,因此可以认为,Zygote开创了Java FrameWork层。进入java层代码后,main函数的完结如下所示:
@UnsupportedAppUsage
public static void main(String argv[]) {
// Server socket class for zygote processes.
ZygoteServer zygoteServer = null; //用来管理和子进程通讯的socket服务端
// Mark zygote start. This ensures that thread creation will throw
// an error.
ZygoteHooks.startZygoteNoThreadCreation(); //这儿其实只是设置一个标志位,为创立Java线程时做判别处理,假如是zygote进程,则不需求开启线程
// Zygote goes into its own process group.
try {
Os.setpgid(0, 0); //为zygote进程设置pgid(Process Group ID),详见:`https://stackoverflow.com/questions/41498383/what-do-the-identifiers-pid-ppid-sid-pgid-uid-euid-mean`
} catch (ErrnoException ex) {
throw new RuntimeException("Failed to setpgid(0,0)", ex);
}
Runnable caller;
try {
// Report Zygote start time to tron unless it is a runtime restart
if (!"1".equals(SystemProperties.get("sys.boot_completed"))) { //获取体系特点,判别体系重启完结
MetricsLogger.histogram(null, "boot_zygote_init",
(int) SystemClock.elapsedRealtime());
}
String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";//判别当前进程是64位程序仍是32位程序,并设置符号
TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,
Trace.TRACE_TAG_DALVIK);
bootTimingsTraceLog.traceBegin("ZygoteInit");
RuntimeInit.enableDdms();//注册到ddms服务端,内部调用`DdmServer.registerHandler()`
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])) { //参数重包括`start-system-server`
startSystemServer = true; //设置标志为位true
} else if ("--enable-lazy-preload".equals(argv[i])) {
enableLazyPreload = true;
} else if (argv[i].startsWith(ABI_LIST_ARG)) { //获取支撑的架构列表
abiList = argv[i].substring(ABI_LIST_ARG.length());
} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);//依据socketName判别是否是primaryZygote,可能还有secondZygote
if (abiList == null) { //假如支撑架构为空,直接抛出异常
throw new RuntimeException("No ABI list supplied.");
}
// In some configurations, we avoid preloading resources and classes eagerly.
// In such cases, we will preload things prior to our first fork.
if (!enableLazyPreload) {
bootTimingsTraceLog.traceBegin("ZygotePreload");
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
preload(bootTimingsTraceLog); //加载各种体系res资源,类资源
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
bootTimingsTraceLog.traceEnd(); // ZygotePreload
} else {
Zygote.resetNicePriority();
}
// Do an initial gc to clean up after startup
bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
gcAndFinalize(); //调用ZygoteHooks.gcAndFinalize()进行垃圾收回
bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC
bootTimingsTraceLog.traceEnd(); // ZygoteInit
// Disable tracing so that forked processes do not inherit stale tracing tags from Zygote.
Trace.setTracingEnabled(false, 0);
Zygote.initNativeState(isPrimaryZygote);//jni调用初始化zygote的状况,是否为isPrimaryZygote
ZygoteHooks.stopZygoteNoThreadCreation(); //结束zygote创立,其实内部是调用`runtime`给`zygote_no_threads_`赋值为false,为创立本地线程做准备
zygoteServer = new ZygoteServer(isPrimaryZygote); //创立zygoteServer,为其他进程初始化创立时与zygote通讯做准备
if (startSystemServer) { //判别是否需求startSystemServer
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);//经过fork的办法开启zygote的子进程,systemServer,并回来一个Runnale对象
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) {//假如是zygote进程,则r==null,假如不是zygote进程,也便是systemServer进程,则履行下面的代码
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); //zygote进程进入死循环中,来获取子进程发送的音讯
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
if (zygoteServer != null) {
zygoteServer.closeServerSocket(); //假如产生异常,则说明zygote初始化失败,zygoteServer也需求关闭
}
}
// We're in the child process and have exited the select loop. Proceed to execute the command.
if (caller != null) {
caller.run();
}
}
zygote java层的大概流程咱们现已整理完了,现在咱们来总结一下:
- 基于传参解析对应的
zygote.rc
脚本,设置进程名为zygote等信息。 - 创立ZygoteServer ,这个server存在的目的是让zygote接纳来自socket的恳求,进而fork进程,zygoteServer里面封装了socket。
- preload(bootTimingsTraceLog):加载体系资源res,加载 Android sdk class资源 和其他libc。
- forkSystemServer,便是fork 产生了SystemServer进程
- 调用
runSelectionLoop()
,接纳其他进程发送的socket音讯,进而创立子进程。
特别说明
调用preload完结体系资源的预加载,首要包括preloadClasses,preloadResources,preloadDrawables,preloadSharedLibraries。这些资源并不是给zygote自己实践显现运用的,它之所以存在,是为后面fork 出来的App去运转而准备的。由于app 进程需求运转就需求framework 层的体系资源,而这些资源就会在这儿得到加载。
总结
zygote进程的发动分为两大部分,榜首部分:履行Native层面的代码,这个进程首要包括:虚拟机发动,JNI资源函数的注册,发动zygote的java层;第二部分:履行java层面的代码,这个进程首要包括:zygote脚本解读,加载共用的各种资源,创立socket服务器并在runSelectionLoop中死循环等候socket音讯,fork 了systemServer进程等操作。
详细重视公众号:Android老皮
还能解锁 《Android十大板块文档》 ,让学习更贴近未来实战。已构成PDF版
内容如下:
1.Android车载使用开发体系学习指南(附项目实战)
2.Android Framework学习指南,助力成为体系级开发高手
3.2023最新Android中高级面试题汇总+解析,离别零offer
4.企业级Android音视频开发学习路线+项目实战(附源码)
5.Android Jetpack从入门到通晓,构建高质量UI界面
6.Flutter技术解析与实战,跨平台首要之选
7.Kotlin从入门到实战,全方面提升架构根底
8.高级Android插件化与组件化(含实战教程和源码)
9.Android 功能优化实战+360全方面功能调优
10.Android零根底入门到通晓,高手进阶之路