1 Overview
In Android
the system, DVM
( Dalvik
virtual machine) and ART
system service process system_server
and application process are all Zygote
created by the process (and Native
the program, that is, C/C++
the program developed by the process is init
created and started by the process). Zygote
The process is also called the incubator. fork(复制进程)
The application process and system_server
the process are created in the form of . Since the process will create or Zygote
when it starts , the application process and process created by passing can obtain an instance copy of or internally .DVM
ART
fork
system_server
DVM
ART
Zygote
A process is init
created when the process starts. Initially, Zygote
the name of the process is not Zygote
, but rather app_process
, the name is /frameworks/base/cmds/app_process/Android.mk
defined in . Zygote
After the process starts, the system Linux
under the system pctrl
will be called app_process
, and its name will be changed to Zygote
.
Zygote
is a C/S
model. Zygote
As a server, the process Socket
communicates with other processes through the method. The "other process" here mainly refers to the system service process system_server
.
In Linux
the system, fork
when calling a function to create a child process, the memory of the parent process will not be copied, but the parent and child processes share a memory space, and the memory copy will only be performed when the child process or the parent process modifies the memory data, thus, The parent process and the child process have their own memory space. Before then, it will only be shared as read-only.
Copy-on-write ( copy-on-write
): The memory space is not actually allocated until the data is modified, which is a technique that can delay or even avoid copying data. This is an optimization of program performance, and the purpose of this is to avoid unnecessary copies.
Zygote
As an incubator, some resources can be loaded in advance, so that fork
the spawned child process can directly use these resources without reloading. For example, system_server
a process can directly use functions, shared libraries, common classes, and theme resources Zygote
in the process JNI
.
Zygote
Process startup works the following things:
- Call
AppRuntime/AndroidRuntime.start
method, createJava
virtual machine and registerJNI
method for it; - Enter the framework layer from the layer by
JNI
calling the method ;ZygoteInit.main
Native
Java
- start
system_server
process; - Create a new application process by
ZygoteServer
creating a request on the server sideSocket
andZygoteServer.runSelectLoop
waiting for it through the method ;AMS
The following is Zygote
the timing diagram for startup:
2 Zygote
startup script
In the process of starting the init process , it is mentioned that init
the process will parse init.rc
the file, and then create and load service
the process specified by the field, and the process is loaded Zygote
by the process in this way . Use the type statement in the file init
to introduce the startup script, which is written by the initialization language ( ):init.rc
Import
Zygote
Android
Android Init Language
// /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} 由厂商定义,与平台无关
It can be seen that init.rc
a fixed file will not be imported directly, but ro.zygote
different files will be imported according to the content.
Starting from Android 5.0
, we began to support 64
1-bit programs, Zygote
so there is a difference 32
between 1-bit and 1 64
-bit, so we use ro.zygote
the attribute to control the use of different Zygote
startup scripts, so that different versions of the process are started , and different versions of the process Zygote
are started . There are the following values :Zygote
ro.zygote
4
init.zygote32.rc
:Zygote
The execution program corresponding to the process isapp_process
(pure32 bit
mode);init.zygote32_64.rc
: Start twoZygote
processes (zygote
andzygote_secondary
), and the corresponding execution programs areapp_process32
(main mode),app_process64
;init.zygote64.rc
:Zygote
The execution program corresponding to the process isapp_process64
(pure64 bit
mode);init.zygote64_32.rc
: Start twoZygote
processes (zygote
andzygote_secondary
), and the corresponding execution programs areapp_process64
(main mode),app_process32
;
These Zygote
startup scripts are placed system/core/rootdir
in the directory as follows:
Taking 64
the bit processor as an example, init.zygote64_32.rc
the code is as follows:
There are two type statements in the script Service
, indicating that two Zygote
processes will be started, one is named zygote
, and the execution program is app_process64
, as the main mode; the other is named zygote_secondary
, and the execution program is app_process32
, as the secondary mode. Other script files are similar to this.
Take init.zygote64_32.rc
for example, its startup file address is /system/bin/app_process64
(above figure), and app_process64
the corresponding code is in /frameworks/base/cmds/app_process
the directory of .
First, take a look at Android.mk
:
// /frameworks/base/cmds/app_process/Android.mk
LOCAL_PATH:= $(call my-dir)
....
app_process_src_files := \
app_main.cpp \
...
LOCAL_MODULE:= app_process
LOCAL_MULTILIB := both
LOCAL_MODULE_STEM_32 := app_process32
LOCAL_MODULE_STEM_64 := app_process64
...
As can be seen from the above code, whether it is app_prcess
or app_prcess32
or app_prcess64
, the corresponding source file is app_main.cpp
.
3 Zygote
process startup process
init
The process is started Zygote
mainly by calling the function app_main.cpp
in the file main
, among which the process is started by AppRuntime
calling the method :start
Zygote
// /frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[])
{
...
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
// 1
// 如果当前运行在Zygote进程中,则将zygote设置为true
zygote = true; // 2
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
// 3
// 如果当前运行在system_server进程中,则将startSystemServer设置为true
startSystemServer = true; // 4
}
...
}
...
if (!niceName.isEmpty()) {
runtime.setArgv0(niceName.string(), true /* setProcName */);
}
// 如果运行在zygote进程中
if (zygote) {
// 5
runtime.start("com.android.internal.os.ZygoteInit", args, zygote); // 6
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
}
}
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
Zygote
Processes fork
create sub-processes by themselves, so that both Zygote
the process and its sub-processes can enter the function app_main.cpp
of , therefore, in order to distinguish which process is currently running in the function,main
main
it will 1
judge arg
whether the parameter is included in the comment --zygote
, if it contains It means that main
the function is running in Zygote
the process, and the comment 2
is zygote
set to true
. In the same way, judge whether 3
the parameter is included in the comment . If it is included, it means that the function trial run is in the process, and set to in the comment .arg
--start-system-server
main
system_server
4
startSystemServer
true
At the comment 5
, if zygote
is true
, it means that it is currently running in zygote
the process, and the function at the comment will be 6
called . Inherited from , and did not override the method, therefore, the process entered in , the code is as follows:AppRuntime
start
AppRuntime
AndroidRuntime
start
Zygote
AndroidRutime
// /frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
...
/* start the virtual machine 启动Java虚拟机 */
JniInvocation jni_invocation;
jni_invocation.Init(NULL);
JNIEnv* env;
if (startVm(&mJavaVM, &env, zygote) != 0) {
// 1
return;
}
onVmCreated(env);
/*
* Register android functions. 为Java虚拟机注册JNI方法
*/
if (startReg(env) < 0) {
// 2
ALOGE("Unable to register all android natives\n");
return;
}
...
// 从app_main的main函数得知className为com.android.internal.os.ZygoteInit
classNameStr = env->NewStringUTF(className); // 3
assert(classNameStr != NULL);
env->SetObjectArrayElement(strArray, 0, classNameStr);
for (size_t i = 0; i < options.size(); ++i) {
jstring optionsStr = env->NewStringUTF(options.itemAt(i).string());
assert(optionsStr != NULL);
env->SetObjectArrayElement(strArray, i + 1, optionsStr);
}
/*
* Start VM. This thread becomes the main thread of the VM, and will
* not return until the VM exits.
* 将className的"."替换为"/"
*/
char* slashClassName = toSlashClassName(className != NULL ? className : ""); // 4
// 找到 zygoteInit
jclass startClass = env->FindClass(slashClassName); // 5
if (startClass == NULL) {
ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
/* keep going */
} else {
// 找到ZygoteInit的main函数
jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
"([Ljava/lang/String;)V"); // 6
if (startMeth == NULL) {
ALOGE("JavaVM unable to find main() in '%s'\n", className);
/* keep going */
} else {
// 通过JNI调用ZygoteInit的main方法
env->CallStaticVoidMethod(startClass, startMeth, strArray); // 7
#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
free(slashClassName);
ALOGD("Shutting down VM\n");
if (mJavaVM->DetachCurrentThread() != JNI_OK)
ALOGW("Warning: unable to detach main thread\n");
if (mJavaVM->DestroyJavaVM() != 0)
ALOGW("Warning: VM did not shut down cleanly\n");
}
1
Call the function in the comment startVm
to create Java
a virtual machine, and 2
call startReg
the function in the comment to Java
register the virtual machine JNI
. 3
The value of in the annotation className
is the parameter passed in, and its value is com.android.internal.os.ZygoteInit
. Use the function at the comment 4
to replace with , and assign the replaced value to , then find at the comment according to , and call the method at the comment after finding . Finally, the method will be called at the comment . Why use here ? Because the method is written in the language, the current running logic is in , which needs to be called through . In this way, the frame layer is entered from the layer .toSlashClassName
className
.
/
com/android/internal/os/ZygoteInit
slashClassName
5
slashClassName
ZygoteInit
ZygoteInit
6
ZygoteInit.main
7
JNI
ZygoteInit.main
JNI
ZygoteInit.main
Java
Native
JNI
Java
Zygote
Native
Java
After JNI
calling ZygoteInit.main
the method, Zygote
you enter Java
the framework layer. Before that, no code entered Java
the framework layer. In other words, you Zygote
created Java
the framework layer. ZygoteInit.main
The method code is as follows:
// /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
// ZygoteServer是Zygote进程的Socket通讯服务端的管理类
ZygoteServer zygoteServer = null;
...
Runnable caller;
try {
if (!enableLazyPreload) {
bootTimingsTraceLog.traceBegin("ZygotePreload");
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
SystemClock.uptimeMillis());
preload(bootTimingsTraceLog); // 1
EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
SystemClock.uptimeMillis());
bootTimingsTraceLog.traceEnd(); // ZygotePreload
} else {
Zygote.resetNicePriority();
}
...
zygoteServer = new ZygoteServer(isPrimaryZygote); // 2
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer); // 3
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
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); // 4
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
if (zygoteServer != null) {
zygoteServer.closeServerSocket();
}
}
...
}
Comments 1
preload classes and resources. The comment 2
creates a channel on the Server
end Socket
that responds to ActivityManagerService
request Zygote
to create a new application process. 3
Start the process at the comment system_server
, so that the system services will also system_server
be started by the process. 4
The method is called at comment ZygoteServer.runSelectLoop
to wait for AMS
a request to create a new process.
From the above, we can see that ZygoteInit.main
the method mainly does 4
two things:
- preload classes and resources ;
- The creation
Server
sideSocket
is used to respond toActivityManagerService
the request to create a new application process; - Start
system_server
the process, so that the system service will alsosystem_server
be started by ; - Waiting for
ActivityManagerService
a request to create a new application process;
reference
[Android 10 System Launch] Series – Zygote (Process Incubator)