涉及源码
android-8.0.0_r1\system\core\rootdir\init.rc
android-8.0.0_r1\system\core\rootdir\init.*.rc
android-8.0.0_r1\frameworks\base\core\java\com\android\internal\os\Zygote.java
android-8.0.0_r1\frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
android-8.0.0_r1\frameworks\base\core\java\com\android\internal\os\ZygoteServer.java
android-8.0.0_r1\frameworks\base\core\java\com\android\internal\os\RuntimeInit.java
概述
通过init.rc启动zygote,以及zygote如何启动system_server和启动app
时序图
关键步骤
- 开机时,解析init.rc,
trigger zygote-start
启动zygote
zygote有4种类型
- zygote32 仅支持32位模式
- zygote64 仅支持64位模式
- zygote64_32 支持64位和32位模式,默认64位主模式
- zygote64_32 支持32位和64位模式,默认32位主模式
系统启动根据具体产品配置(一般位device目录下的device.mk)启动相应类型虚拟机。由于64位越来越主流,流程主要跟踪64位模式
- init.zygote64.rc文件中定义了启动zygote的服务
# file: system\core\rootdir\init.zygote64.rc
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc
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
通过运行64位的app_process启动zygote
-
虚拟机创建完,运行java程序初始阶段,进行资源加载。资源加载有两种方式:
3.1 预加载:在启动过程中,提前加载资源
3.2 资源延后加载,通过zygote启动过程中创建的socket通知加载 -
zygote启动过程中,通过startSystemServer启动system_server,该函数引发的流程会创建一个新进程来启动system_server
-
system_server启动完成后,在zygote进程中,会监听一个socket,用来处理启动app或延后加载资源等。
public static void main(String argv[]) {
...
// 启动systemserver变量
boolean startSystemServer = false;
String socketName = "zygote";
String abiList = null;
// 资源懒加载变量
boolean enableLazyPreload = false;
for (int i = 1; i < argv.length; i++) {
if ("start-system-server".equals(argv[i])) {
startSystemServer = 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)) {
socketName = argv[i].substring(SOCKET_NAME_ARG.length());
} else {
throw new RuntimeException("Unknown command line argument: " + argv[i]);
}
}
...
// 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);
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
bootTimingsTraceLog.traceEnd(); // ZygotePreload
} else {
Zygote.resetNicePriority();
}
...
if (startSystemServer) {
// 启动system_server
startSystemServer(abiList, socketName, zygoteServer);
}
Log.i(TAG, "Accepting command socket connections");
// 监听socket,接收命令并处理
zygoteServer.runSelectLoop(abiList);
zygoteServer.closeServerSocket();
} catch (Zygote.MethodAndArgsCaller caller) {
caller.run();
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
zygoteServer.closeServerSocket();
throw ex;
}
}
预加载
static void preload(BootTimingsTraceLog bootTimingsTraceLog) {
Log.d(TAG, "begin preload");
bootTimingsTraceLog.traceBegin("BeginIcuCachePinning");
beginIcuCachePinning();
bootTimingsTraceLog.traceEnd(); // BeginIcuCachePinning
bootTimingsTraceLog.traceBegin("PreloadClasses");
// 根据/system/etc/preloaded-classes预加载类,通过优化该文件,优化内存和启动速度
preloadClasses();
bootTimingsTraceLog.traceEnd(); // PreloadClasses
bootTimingsTraceLog.traceBegin("PreloadResources");
// 加载res目录下资源
preloadResources();
bootTimingsTraceLog.traceEnd(); // PreloadResources
Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadOpenGL");
// 加载OpenGL应用驱动
preloadOpenGL();
Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
// 加载系统核心共享库
preloadSharedLibraries();
// 加载字体
preloadTextResources();
// Ask the WebViewFactory to do any initialization that must run in the zygote process,
// for memory sharing purposes.
WebViewFactory.prepareWebViewInZygote();
endIcuCachePinning();
warmUpJcaProviders();
Log.d(TAG, "end preload");
sPreloadComplete = true;
}