一:背景
众所周知,Android应用及system_server基本都是由zygote fork出来的,那么zygote是如何启动的、又是如何接收fork进程的请求,接下来一步步揭秘。
二:启动流程
init进程是Android系统启动时,启动的第一个进程,其他所有进程基本都是由init进程来启动,其中也包括zygote,下面看下zygote的启动。
2.1 init进程启动zygote
init.rc里,在late-init阶段会触发zygote-start,zygote-start会启动zygote服务。在zygote服务中会启动app_process64(即zygote)并传入必要参数。
//system/core/rootdir/init.rc
on late-init...# Now we can start zygote.trigger zygote-start...//system/core/rootdir/init.rc
on zygote-start...# 启动zygote服务start zygotestart zygote_secondary//system/core/rootdir/init.zygote64.rc
#启动app_process64时传参:-Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygoteclass mainpriority -20...
2.2 zygote初始化
2.2.1 AndroidRuntime.start
- 启动java虚拟机,根据"dalvik.vm.xxx"属性值进行初始化
- 注册jni函数
- 调用ZygoteInit的main函数
//frameworks/base/cmds/app_main.cpp
int main(int argc, char* const argv[])
{...bool zygote = false;bool startSystemServer = false;bool application = false;String8 niceName;String8 className;++i; // Skip unused "parent dir" argument.//获取启动参数并根据参数初始化zygote、startSystemServer等值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 = (arg + 12);} else if (strncmp(arg, "--", 2) != 0) {className = arg;break;} else {--i;break;}}...if (zygote) {runtime.start("com.android.internal.os.ZygoteInit", args, zygote);...
}//frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{...bool primary_zygote = false;for (size_t i = 0; i < options.size(); ++i) {if (options[i] == startSystemServer) {primary_zygote = true;/* track our progress through the boot sequence */const int LOG_BOOT_PROGRESS_START = 3000;LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));addBootEvent("boot_progress_start");}}...//启动java虚拟机,根据"dalvik.vm.xxx"属性值进行初始化if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {return;}...//注册jni函数if (startReg(env) < 0) {ALOGE("Unable to register all android natives\n");return;}...//将className中的.替换为/ ,转换之后slashClassName的值为"com/android/internal/os/ZygoteInit"char* slashClassName = toSlashClassName(className != NULL ? className : "");jclass startClass = env->FindClass(slashClassName);if (startClass == NULL) {...} else {//获取main函数jmethodID startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");if (startMeth == NULL) {...} else {//调用ZygoteInit的main函数env->CallStaticVoidMethod(startClass, startMeth, strArray);}}...
}
2.2.2 ZygoteInit.main
- 在fork前做一些初始化工作,主要是enable DDMS
- 提前加载框架通用类和系统资源
- fork进程之前进行一次gc
- 初始化seLinux
- 初始化storage
- 创建zygote的服务端对象
//frameworks/base/core/java/com/android/internal/os/ZygoteInit.javapublic static void main(String[] argv) {ZygoteServer zygoteServer = null;...//zygote运行在单独的进程组中try {Os.setpgid(0, 0);}...Runnable caller;try {...bootTimingsTraceLog.traceBegin("ZygoteInit");//做fork前的一些初始化工作,主要是enable DDMSRuntimeInit.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])) {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)) {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);...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}bootTimingsTraceLog.traceBegin("PostZygoteInitGC");//fork进程之前进行一次gcgcAndFinalize();bootTimingsTraceLog.traceEnd(); // PostZygoteInitGCbootTimingsTraceLog.traceEnd(); // ZygoteInit...//native初始化Zygote.initNativeState(isPrimaryZygote);...//创建zygote的服务端对象zygoteServer = new ZygoteServer(isPrimaryZygote);if (startSystemServer) {//fork system_server进程Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);if (r != null) {r.run();return;}}...caller = zygoteServer.runSelectLoop(abiList);}...//在单独的线程中接收来自应用的zygote请求if (caller != null) {caller.run();}}//frameworks/base/core/java/com/android/internal/os/ZygoteInit.javastatic void preload(TimingsTraceLog bootTimingsTraceLog) {...//加载/system/etc/preloaded-classes定义的所有的类preloadClasses();...//加载frameworks/base/core/res/res/values/arrays.xml中preloaded_drawables和preloaded_color_state_lists定义的所有资源Resources.preloadResources();...//加载graphic的halnativePreloadAppProcessHALs();...//加载graphicmaybePreloadGraphicsDriver();...//加载android、jnigraphics、compiler_rt这三个共享库preloadSharedLibraries();//加载字体资源preloadTextResources();...}//frameworks/base/core/java/com/android/internal/os/Zygote.javastatic void initNativeState(boolean isPrimary) {nativeInitNativeState(isPrimary);}//frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
static void com_android_internal_os_Zygote_nativeInitNativeState(JNIEnv* env, jclass,jboolean is_primary) {//从环境中获取init创建的文件描述符。gZygoteSocketFD =android_get_control_socket(is_primary ? "zygote" : "zygote_secondary");...//创建用于向system_server发送未经请求的消息的socket,在app申请zygote fork进程时被调用,fork完成后关闭initUnsolSocketToSystemServer();...//初始化seLinuxgIsSecurityEnforced = security_getenforce();selinux_android_seapp_context_init();//初始化storageUnmountStorageOnInit(env);//设置高优先级if (!SetTaskProfiles(0, {})) {zygote::ZygoteFailure(env, "zygote", nullptr, "Zygote SetTaskProfiles failed");}
}
2.2.3 ZygoteInit.forkSystemServer
- 设置启动system_server的参数,例如uid、gid、进程名称等
- 调用Linux的fork函数来实现fork system_server进程
//frameworks/base/core/java/com/android/internal/os/ZygoteInit.javaprivate static Runnable forkSystemServer(String abiList, String socketName,ZygoteServer zygoteServer) {...//设置启动system_server的参数String[] args = {"--setuid=1000","--setgid=1000","--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"+ "1024,1032,1065,3001,3002,3003,3005,3006,3007,3009,3010,3011,3012","--capabilities=" + capabilities + "," + capabilities,"--nice-name=system_server","--runtime-args","--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,"com.android.server.SystemServer",};...try {...//fork system_serverpid = Zygote.forkSystemServer(...);}...//子进程if (pid == 0) {...zygoteServer.closeServerSocket();return handleSystemServerProcess(parsedArgs);}...}//frameworks/base/core/java/com/android/internal/os/Zygote.javastatic int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {ZygoteHooks.preFork();int pid = nativeForkSystemServer(uid, gid, gids, runtimeFlags, rlimits,permittedCapabilities, effectiveCapabilities);//设置线程优先级为NORM_PRIORITYThread.currentThread().setPriority(Thread.NORM_PRIORITY);//ZygoteHooks.postForkCommon是Zygote进程中的一个钩子函数,它在Zygote进程fork出子进程后被调用。这个钩子函数的作用是在子进程中执行一些初始化操作,例如创建Binder线程池和消息循环等。ZygoteHooks.postForkCommon();return pid;}//frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
static jint com_android_internal_os_Zygote_nativeForkSystemServer(...) {...pid_t pid = zygote::ForkCommon(env, true,fds_to_close,fds_to_ignore,true);...return pid;
}//frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
pid_t zygote::ForkCommon(JNIEnv* env, bool is_system_server,const std::vector<int>& fds_to_close,const std::vector<int>& fds_to_ignore,bool is_priority_fork,bool purge) {ATRACE_CALL();if (is_priority_fork) {//设置最大优先级setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MAX);}//设置信号处理程序SetSignalHandlers();...//阻断信号BlockSignal(SIGCHLD, fail_fn);...//真正fork进程的地方,在父进程中,fork()返回新创建子进程的PID,而在子进程中,fork()返回0。pid_t pid = fork();...//解除阻断信号UnblockSignal(SIGCHLD, fail_fn);if (is_priority_fork && pid != 0) {//设置优先级为PROCESS_PRIORITY_DEFAULTsetpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_DEFAULT);}return pid;
}
2.2.4 RuntimeInit.applicationInit
- 获取SystemServer.java类对应的ClassLoader
- 初始化时区、User-Agent等
- 开启线程池
- 调用SystemServer的main函数,开始启动系统服务等
这个时候system_server进程就启动了,开始启动系统服务等
//frameworks/base/core/java/com/android/internal/os/ZygoteInit.javaprivate static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {...if (parsedArgs.mInvokeWith != null) {...} else {//获取SystemServer.java类对应的ClassLoaderClassLoader cl = getOrCreateSystemServerClassLoader();...return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,parsedArgs.mDisabledCompatChanges,parsedArgs.mRemainingArgs, cl);}}//frameworks/base/core/java/com/android/internal/os/ZygoteInit.javapublic static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,String[] argv, ClassLoader classLoader) {...//初始化时区、User-Agent等RuntimeInit.commonInit();//开启线程池ZygoteInit.nativeZygoteInit();return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,classLoader);}//frameworks/base/core/java/com/android/internal/os/RuntimeInit.javaprotected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,String[] argv, ClassLoader classLoader) {...return findStaticMain(args.startClass, args.startArgs, classLoader);}//frameworks/base/core/java/com/android/internal/os/RuntimeInit.javaprotected static Runnable findStaticMain(String className, String[] argv,ClassLoader classLoader) {Class<?> cl;try {//获取SystemServer类cl = Class.forName(className, true, classLoader);}...Method m;try {//获取main函数m = cl.getMethod("main", new Class[] { String[].class });}...//调用SystemServer的main函数,开始启动系统服务等return new MethodAndArgsCaller(m, argv);}
2.2.5 ZygoteServer.runSelectLoop
在线程里启动一个死循环,接收请求fork的socket请求
//frameworks/base/core/java/com/android/internal/os/ZygoteServer.javaRunnable runSelectLoop(String abiList) {...while (true) {...if (pollReturnValue == 0) {...} else {...while (--pollIndex >= 0) {if (pollIndex == 0) {...} else if (pollIndex < usapPoolEventFDIndex) {try {//获取socket连接ZygoteConnection connection = peers.get(pollIndex);boolean multipleForksOK = !isUsapPoolEnabled()&& ZygoteHooks.isIndefiniteThreadSuspensionSafe();//处理来自应用请求fork的socket请求final Runnable command =connection.processCommand(this, multipleForksOK);}...}}...}...}}
三:小结
3.1 zygote进程是否只有一个?
答:不是。
zygote进程一般都会有zygote和zygote64两个,分别用来fork32位和64位的应用,这两个进程都是在init.rc中启动的。
如果系统中有webview类应用,那么还会存在webview_zygote这个进程,用来fork webview类应用。webview_zygote进程的启动是在ProcessList的startProcess函数中判断是否是webview类型应用,如果是则会调用Process的startWebView函数,接着会判断webview_zygote进程是否存在,如果不存在则调用zygote fork出来。
3.2 是否每次应用冷启动时都要调用zygote的fork函数?
答:不是。
Android系统有usap机制,会在Android系统启动时,开启一个进程池。如果usap功能打开,当有fork请求到来时,会先从进程池中取出一个进程返回,节约启动时间。