zygote,在英语中是受精卵的意思。而在Android系统中也有这么一个“受精卵进程” – Zygote进程。
在Android系统中,Zygote进程是所有Android进程的父进程。它通过fork的形式,创建SystemServer进程和应用程序进程。而Zygote进程则是通过linux系统的init进程启动的。
在Android系统中各种进程的启动过程:init进程 ––> Zygote进程 ––> SystemServer进程 ––>各种应用进程
其中,应用程序进程即我们编写的应用的进程,SystemServer进程为系统服务进程,比如后面还要学到的AMS、WMS都是在该进程中。
需要注意的是:
1、Android中所有的应用进程的创建都是一个应用进程通过Binder请求SystemServer进程,SystemServer进程发送socket消息给Zygote进程,统一由Zygote进程创建出来的。
2、Zygote进程在启动的时候会创建一个虚拟机实例,因此通过Zygote进程在父进程,创建的子进程都会继承这个虚拟机实例,App中的JAVA代码可以得到翻译执行。
3、进程与进程之间需要跨进程通信,由Zygote进程作为父进程还可以获得一个Binder线程池,这样进程之间就可以使用Binder进行跨进程通信了。
192int main(int argc, char* const argv[])
193{
...
282 // Parse runtime arguments. Stop at first unrecognized option.
283 bool zygote = false;
284 bool startSystemServer = false;
285 bool application = false;
286 String8 niceName;
287 String8 className;
288
289 ++i; // Skip unused "parent dir" argument.
//init.rc中会配置一些参数,这里进行比较设置一些变量走进不同的分支
290 while (i < argc) {
291 const char* arg = argv[i++];
292 if (strcmp(arg, "--zygote") == 0) {
//启动的是Zygote进程
293 zygote = true;
294 niceName = ZYGOTE_NICE_NAME;
295 } else if (strcmp(arg, "--start-system-server") == 0) {
//启动的是system-server进程
296 startSystemServer = true;
297 } else if (strcmp(arg, "--application") == 0) {
298 application = true;
299 } else if (strncmp(arg, "--nice-name=", 12) == 0) {
300 niceName.setTo(arg + 12);
301 } else if (strncmp(arg, "--", 2) != 0) {
302 className.setTo(arg);
303 break;
304 } else {
305 --i;
306 break;
307 }
308 }
309
...
//设置一个“好听的名字” zygote,之前的名称是app_process
357 if (!niceName.isEmpty()) {
358 runtime.setArgv0(niceName.string(), true /* setProcName */);
359 }
360
361 if (zygote) {
//通过runtime启动zygote
364 runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
365 } else if (className) {
366 runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
367 } else {
368 fprintf(stderr, "Error: no class name or --zygote supplied.\n");
369 app_usage();
370 LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
371 }
372}
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
1057{
1058 ALOGD(">>>>>> START %s uid %d <<<<<<\n",
1059 className != NULL ? className : "(unknown)", getuid());
1060
1061 static const String8 startSystemServer("start-system-server");
1062
1063 /*
1064 * 'startSystemServer == true' means runtime is obsolete and not run from
1065 * init.rc anymore, so we print out the boot start event here.
1066 */
1067 for (size_t i = 0; i < options.size(); ++i) {
1068 if (options[i] == startSystemServer) {
1069 /* track our progress through the boot sequence */
1070 const int LOG_BOOT_PROGRESS_START = 3000;
1071 LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC)));
1072 }
1073 }
1074
1075 const char* rootDir = getenv("ANDROID_ROOT");
1076 if (rootDir == NULL) {
1077 rootDir = "/system";
1078 if (!hasDir("/system")) {
1079 LOG_FATAL("No root directory specified, and /android does not exist.");
1080 return;
1081 }
1082 setenv("ANDROID_ROOT", rootDir, 1);
1083 }
1084
1085 //const char* kernelHack = getenv("LD_ASSUME_KERNEL");
1086 //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);
1087
1088 /* start the virtual machine */
1089 JniInvocation jni_invocation;
1090 jni_invocation.Init(NULL);
1091 JNIEnv* env;
1092 if (startVm(&mJavaVM, &env, zygote) != 0) {
1093 return;
1094 }
1095 onVmCreated(env);
1096
1097 /*
1098 * Register android functions.
1099 */
1100 if (startReg(env) < 0) {
1101 ALOGE("Unable to register all android natives\n");
1102 return;
1103 }
1104
1105 /*
1106 * We want to call main() with a String array with arguments in it.
1107 * At present we have two arguments, the class name and an option string.
1108 * Create an array to hold them.
1109 */
1110 jclass stringClass;
1111 jobjectArray strArray;
1112 jstring classNameStr;
1113
1114 stringClass = env->FindClass("java/lang/String");
1115 assert(stringClass != NULL);
1116 strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
1117 assert(strArray != NULL);
1118 classNameStr = env->NewStringUTF(className);
1119 assert(classNameStr != NULL);
1120 env->SetObjectArrayElement(strArray, 0, classNameStr);
1121
1122 for (size_t i = 0; i < options.size(); ++i) {
1123 jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
1124 assert(optionsStr != NULL);
1125 env->SetObjectArrayElement(strArray, i + 1, optionsStr);
1126 }
1127
1128 /*
1129 * Start VM. This thread becomes the main thread of the VM, and will
1130 * not return until the VM exits.
1131 */
1132 char* slashClassName = toSlashClassName(className != NULL ? className : "");
1133 jclass startClass = env->FindClass(slashClassName);
1134 if (startClass == NULL) {
1135 ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
1136 /* keep going */
1137 } else {
1138 jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
1139 "([Ljava/lang/String;)V");
1140 if (startMeth == NULL) {
1141 ALOGE("JavaVM unable to find main() in '%s'\n", className);
1142 /* keep going */
1143 } else {
1144 env->CallStaticVoidMethod(startClass, startMeth, strArray);
1145
1146#if 0
1147 if (env->ExceptionCheck())
1148 threadExitUncaughtException(env);
1149#endif
1150 }
1151 }
1152 free(slashClassName);
1153 //这行Log比较常见,因为其他应用进程也是由zygote 进程fork 出来的,所有其他进程也包含这段代码,如果其他进程在java 层crash,那么也会走到这里
1154 ALOGD("Shutting down VM\n");
1155 if (mJavaVM->DetachCurrentThread() != JNI_OK)
1156 ALOGW("Warning: unable to detach main thread\n");
1157 if (mJavaVM->DestroyJavaVM() != 0)
1158 ALOGW("Warning: VM did not shut down cleanly\n");
1159}
主要做了三件事情,1、调用startVm开启虚拟机,2、调用startReg注册JNI方法,3、使用JNI把Zygote进程启动起来。启动的类名为 com.android.internal.os.ZygoteInit,方法名为main。
public static void main(String argv[]) {
//1、创建ZygoteServer
ZygoteServer zygoteServer = new ZygoteServer();
//此处开启设置,创建过程禁止多线程,为什么?后面会解答
ZygoteHooks.startZygoteNoThreadCreation();
...
try {
...
//设置DDMS可用
RuntimeInit.enableDdms();
//初始化启动参数
boolean startSystemServer = false;
String socketName = "zygote";
String abiList = null;
boolean enableLazyPreload = false;
// 2、解析app_main.cpp传来的参数
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]);
}
}
if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
}
//3、创建一个Server端的Socket
zygoteServer.registerServerSocketFromEnv(socketName);
// 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());
//4、预加载进程的资源和类
preload(bootTimingsTraceLog);
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
bootTimingsTraceLog.traceEnd(); // ZygotePreload
} else {
Zygote.resetNicePriority();
}
...
//此处关闭设置,允许多线程
ZygoteHooks.stopZygoteNoThreadCreation();
//5、fork一个SystemServer进程
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
if (r != null) {
r.run();
return;
}
}
//6、启动一个死循环,监听socket,启动新的应用进程
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
zygoteServer.closeServerSocket();
throw ex;
} finally {
zygoteServer.closeServerSocket();
}
if (caller != null) {
caller.run();
}
}
总结一下,在main方法中主要完成了6件事:
void registerServerSocketFromEnv(String socketName) {
if (mServerSocket == null) {
int fileDesc;
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
//从环境变量中获取名为ANDROID_SOCKET_zygote的fd
String env = System.getenv(fullSocketName);
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException(fullSocketName + " unset or invalid", ex);
}
try {
//创建一个FD对象
FileDescriptor fd = new FileDescriptor();
fd.setInt$(fileDesc);
//不是使用IP和端口,这里用这个FD创建LocalServerSocket
mServerSocket = new LocalServerSocket(fd);
mCloseSocketFd = true;
} catch (IOException ex) {
throw new RuntimeException(
"Error binding to local socket '" + fileDesc + "'", ex);
}
}
}
注意,这时通过fd创建了一个socket服务端–LocalServerSocket。当Zygote进程将SystemServer进程启动后,就会在这个服务端的Socket上来等待ActivityManagerService请求Zygote进程来创建新的应用程序进程。
这里为什么是使用FD创建呢?LocalServerSocket具体是怎么创建的?
具体可以查看 -> https://www.jianshu.com/p/ab9b83a77af6
static void preload(TimingsTraceLog bootTimingsTraceLog) {
124 Log.d(TAG, "begin preload");
125 bootTimingsTraceLog.traceBegin("BeginIcuCachePinning");
126 beginIcuCachePinning();
127 bootTimingsTraceLog.traceEnd(); // BeginIcuCachePinning
128 bootTimingsTraceLog.traceBegin("PreloadClasses");
//预加载类,在preloadClasses方法中会通过Class.forName将类加载到系统中,生成字节码
129 preloadClasses();
130 bootTimingsTraceLog.traceEnd(); // PreloadClasses
131 bootTimingsTraceLog.traceBegin("PreloadResources");
//预加载资源文件
132 preloadResources();
133 bootTimingsTraceLog.traceEnd(); // PreloadResources
134 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadAppProcessHALs");
135 nativePreloadAppProcessHALs();
136 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
137 Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadOpenGL");
138 preloadOpenGL();
139 Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
//预加载共享库
140 preloadSharedLibraries();
//预加载文字资源
141 preloadTextResources();
142 // Ask the WebViewFactory to do any initialization that must run in the zygote process,
143 // for memory sharing purposes.
144 WebViewFactory.prepareWebViewInZygote();
145 endIcuCachePinning();
146 warmUpJcaProviders();
147 Log.d(TAG, "end preload");
148
149 sPreloadComplete = true;
150 }
从代码中,我们可以看到哪些资源会被进行预加载:类文件、资源文件、共享库、文字资源。总的来说,这些都是系统中App共享的资源。通过此时预加载,可以减少资源加载时间,加快了应用启动速度。
在preloadClasses()函数中,会通过Class.forName将类加载到系统中,生成字节码。此时预加载的类有哪些,可以查看清单:http://androidxref.com/8.0.0_r4/xref/frameworks/base/preloaded-classes
注意:这里预加载资源都是在主线程中完成的,为什么不开多线程呢?猜测是防止多线程带来的同步问题。所以才在ZygoteInit的方法中开启了禁止多线程的设置,完成后才关闭。