基于Android10.0的源码分析Android启动的Zygote进程
Zygote这个词的字面意思是“受精卵”,因而可以孕育出一个新生命。正如其所示Android中大多数应用进程和系统进程都是Zygote来生成的。 那么Zygote是如何启动的,也是由init解析rc脚本时启动。早期Android版本zygote命令直接写在init.rc中,但是随着硬件不断升级换代,Android系统不的不面对32位和64位机器同时存在情况,因为对zygote启动也需要根据不同情况区分对待:?
/system/core/rootdir/init.rc
import /init.environ.rc
import /init.usb.rc
import /init.${ro.hardware}.rc
import /vendor/etc/init/hw/init.${ro.hardware}.rc
import /init.usb.configfs.rc
import /init.${ro.zygote}.rc
根据ro.zygote的具体值,我们需要加载不同的zygote的rc脚本,例如:??
init.zygote32.rc
init.zygote32_64.rc
init.zygote64.rc
init.zygote64_32.rc
我们以init.zygote64.rc为例子,相关代码如下:?
1 service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
2 class main
3 priority -20
4 user root
5 group root readproc reserved_disk
6 socket zygote stream 660 root system
7 socket usap_pool_primary stream 660 root system
8 onrestart write /sys/android_power/request_state wake
9 onrestart write /sys/power/state on
10 onrestart restart audioserver
11 onrestart restart cameraserver
12 onrestart restart media
13 onrestart restart netd
14 onrestart restart wificond
15 writepid /dev/cpuset/foreground/tasks
从该段脚本看出:?
服务名(Servicename): zygote?
路径(Path): /system/bin/app_process64
参数(Arguments): -Xzygote? /system/bin? --start-system-server?
Zygote所属的class为main,而不是core。从路径可以看出,它所在程序名叫“app_process64”。通过--zygote参数,app_process可以识别出用户是否需要启动zygote,我们来看下app_process是什么?源码路径frameworks/base/cmds/ ,先看它的Android.mk?
1 LOCAL_PATH:= $(call my-dir)
2
3 app_process_common_shared_libs := \
4 libandroid_runtime \
5 libbinder \
6 libcutils \
7 libdl \
8 libhidlbase \
9 liblog \
10 libnativeloader \
11 libutils \
12
13 # This is a list of libraries that need to be included in order to avoid
14 # bad apps. This prevents a library from having a mismatch when resolving
15 # new/delete from an app shared library.
16 # See b/21032018 for more details.
17 app_process_common_shared_libs += \
18 libwilhelm \
19
20 app_process_common_static_libs := \
21 libsigchain \
22
23 app_process_src_files := \
24 app_main.cpp \
......
45 LOCAL_MODULE:= app_process
46 LOCAL_MULTILIB := both
47 LOCAL_MODULE_STEM_32 := app_process32
48 LOCAL_MODULE_STEM_64 := app_process64
上述就是Multilib(64位和32位系统)的一个编译脚本范例。其中LOCAL_MULTLIB用于希望针对的硬件架构平台。
分析一下函数app_process的主函数实现:
int main(int argc,char* const argv) {
.....
257 bool zygote = false;
258 bool startSystemServer = false;
259 bool application = false;
260 String8 niceName;
261 String8 className;
262
263 ++i; // Skip unused "parent dir" argument.
264 while (i < argc) {
265 const char* arg = argv[i++];
266 if (strcmp(arg, "--zygote") == 0) {
267 zygote = true;
268 niceName = ZYGOTE_NICE_NAME;
269 } else if (strcmp(arg, "--start-system-server") == 0) {
270 startSystemServer = true;
271 } else if (strcmp(arg, "--application") == 0) {
272 application = true;
273 } else if (strncmp(arg, "--nice-name=", 12) == 0) {
274 niceName.setTo(arg + 12);
275 } else if (strncmp(arg, "--", 2) != 0) {
276 className.setTo(arg);
277 break;
278 } else {
279 --i;
280 break;
281 }
282 }
.....
335 if (zygote) {
336 runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
337 } else if (className) {
338 runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
339 } else {
340 fprintf(stderr, "Error: no class name or --zygote supplied.\n");
341 app_usage();
342 LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
343 }
}
这个函数解析了启动app_process时传入参数:
--zygote : 表示当前进程用于承载zygote 。
--start-system-server : 是否需要驱动system_server 。
--application:启动进入独立的程序模式。?
--nice-name:此进程的 “别名” 。
整一个场景中,init.rc 指定了--zygote选项,所以app_process接下来启动ZygoteInit,并且传入了“start-system-server”。之后ZygoteInit会运行Java虚拟机上,这是因为runtime就是AndroidRuntime,我们看下AndroidRuntime核心start代码?
frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
......
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
onVmCreated(env);
对于虚拟机具体启动和运行过程,本章略过 。
那么虚拟及启动成功后,并进入ZygoteInit的执行中:
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
try {
......
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]);
}
}
if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
}
// In such cases, we will preload things prior to our first fork.
if (!enableLazyPreload) {
// 预加载各类资源
preload(bootTimingsTraceLog);
}
Zygote.initNativeState(isPrimaryZygote);
ZygoteHooks.stopZygoteNoThreadCreation();
// 注册一个Socket
zygoteServer = new ZygoteServer(isPrimaryZygote);
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
if (r != null) {
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);
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
if (zygoteServer != null) {
zygoteServer.closeServerSocket();
}
}
我们可以看到ZygoteInit主函数主要完成以下几项工作:
1. 注册一个socket?
2. 预加载各类资源
包括:
? ? ? ? ? preloadClasses();
? ? ? ? ? cacheNonBootClasspathClassLoaders();
? ? ? ? ? preloadResources();
? ? ? ? ? nativePreloadAppProcessHALs();
? ? ? ? ? maybePreloadGraphicsDriver();
? ? ? ? ? preloadSharedLibraries();
? ? ? ? ? preloadTextResources();
? ? ? ? ? WebViewFactory.prepareWebViewInZygote();
已preloadClasses为例子,他负责加载和初始化常用的一些calsses,这个记录都是在framework/base/tools/preload/WritePreloadClassFile.java生成的 。
因为app_aprocess的调用带有“--start-system-server”,那么此时就会通过forkSystemServer函数来启动System Server。
/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
private static Runnable forkSystemServer(String abiList, String socketName,
725 ZygoteServer zygoteServer) {
String args[] = {
754 "--setuid=1000",
755 "--setgid=1000",
756 "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,"
757 + "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
758 "--capabilities=" + capabilities + "," + capabilities,
759 "--nice-name=system_server",
760 "--runtime-args",
761 "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
762 "com.android.server.SystemServer",
763 };
764 ZygoteArguments parsedArgs = null;
765
766 int pid;
767
768 try {
769 parsedArgs = new ZygoteArguments(args);
770 Zygote.applyDebuggerSystemProperty(parsedArgs);
771 Zygote.applyInvokeWithSystemProperty(parsedArgs);
772
773 boolean profileSystemServer = SystemProperties.getBoolean(
774 "dalvik.vm.profilesystemserver", false);
775 if (profileSystemServer) {
776 parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
777 }
778
779 /* Request to fork the system server process */
780 pid = Zygote.forkSystemServer(
781 parsedArgs.mUid, parsedArgs.mGid,
782 parsedArgs.mGids,
783 parsedArgs.mRuntimeFlags,
784 null,
785 parsedArgs.mPermittedCapabilities,
786 parsedArgs.mEffectiveCapabilities);
787 } catch (IllegalArgumentException ex) {
788 throw new RuntimeException(ex);
789 }
790
791 /* For child process */
792 if (pid == 0) {
793 if (hasSecondZygote(abiList)) {
794 waitForSecondaryZygote(socketName);
795 }
796
797 zygoteServer.closeServerSocket();
798 return handleSystemServerProcess(parsedArgs);
799 }
800
801 return null;
}
上述的代码又出现了fork流程--forkSytemServer在利用内部UNIX的fork机制来创建一个新进程。?
随后在执行过程中通过handleSystemServerProcess来启动各种支撑系统运行的System Server 。?
我们来分析一下Zygote的工作做一个分析,forkSystemServer中并没有为父进程专门开辟一个代码分支,返回很正常Runnable后,返回到了ZygoteInit函数的 runSelectLoop ,我们可以看到这是一个死循环 ,除非Zygote退出或者异常才会跳出循环。?
我们从runSelectLoop函数的?
Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> socketFDs = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
socketFDs.add(mZygoteSocket.getFileDescriptor());
peers.add(null);
获取到前面的ZygoteServer创建的Server Socket文件描述符,他会被添加到ArrayList<FileDescriptor>类型的fds中。
当有客户端的数据需要处理时候,完成具体工作是processOneCommand 函数?
/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
fd = null;
266
267 pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids,
268 parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo,
269 parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote,
270 parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mTargetSdkVersion);
271
272 try {
273 if (pid == 0) {
274 // in child
275 zygoteServer.setForkChild();
276
277 zygoteServer.closeServerSocket();
278 IoUtils.closeQuietly(serverPipeFd);
279 serverPipeFd = null;
280
281 return handleChildProc(parsedArgs, descriptors, childPipeFd,
282 parsedArgs.mStartChildZygote);
283 } else {
284 // In the parent. A pid < 0 indicates a failure and will be handled in
285 // handleParentProc.
286 IoUtils.closeQuietly(childPipeFd);
287 childPipeFd = null;
288 handleParentProc(pid, descriptors, serverPipeFd);
289 return null;
290 }
zygote需要为每个新启动的应用程序生成独立的进程。. 不过没有直接用fork来完成,而是调用了forkAndSpecialize函数,新进程运行应用程序本身代码,这些工作在函数 handleChildProc函数中进行。?
我们跟一下forkAndSpecialize函数:?
public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
235 int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
236 int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir,
237 int targetSdkVersion) {
238 ZygoteHooks.preFork();
239 // Resets nice priority for zygote process.
240 resetNicePriority();
241 int pid = nativeForkAndSpecialize(
242 uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
243 fdsToIgnore, startChildZygote, instructionSet, appDataDir);
244 // Enable tracing as soon as possible for the child process.
245 if (pid == 0) {
246 Zygote.disableExecuteOnly(targetSdkVersion);
247 Trace.setTracingEnabled(true, runtimeFlags);
248
249 // Note that this event ends at the end of handleChildProc,
250 Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
251 }
252 ZygoteHooks.postForkCommon();
253 return pid;
254 }
处理分为3个阶段:preFork? 、 nativeForkAndSpecialize 、postForkCommon?
从以上的分析可以得知,Zygote进程启动中承担的主要职责如下:
参考:
书籍: 深入理解Android内核设计思想 第2版(上册)