preface

Zygote is one of the most frequently asked questions in an interview for Android development, but it’s not always a good question to answer. What do you want to hear and what do you really want to hear? Below we through the following points to analyze this problem!

  • Find out what Zygote does
  • Familiar with Zygote startup process
  • Deeply understand the working principle of Zygote

Here we come to in-depth analysis, at the same time, this article has been included in my Github: Android Note, there are more problems resolved, we can refer to learn!

First, the role of Zygote

The effects of Zygote fall into two categories:

  • Start the SystemServer
  • Incubation application Process

OK if you answer both of these questions. Most of you can probably answer the second point, but the first point is not so clear. Zygote is also used to start SystemServer, because SystemServer needs to use Zygote prepared system resources include:

Inheriting directly from Zygote does not require reloading, which is a huge performance boost.

Two, Zygote startup process

2.1 Three-stage startup

Before we talk about the Zygote startup process, let’s clarify a concept: the three-step startup process, which can be understood as the common Android process startup routine, is divided into three steps:

In fact, LOOP is used to continuously receive and process messages. The source of messages can be Soket, MessageQueue or Binder driver, but no matter where the message comes from, its whole process is to receive and process the message. This startup three-step is not only true for Zygote processes, but also for independent processes, such as system service processes, and their own application processes.

2.2 How is Zygote started?

The Zygote process depends on the init process, which is the first process in user space after Linux is started.

  1. Linux starts the init process
  2. Load the init.rc configuration file after the init process starts

  1. Start the system services defined in the configuration file, where Zygote service is defined in the configuration

  1. In addition to Zygote, some other system services are also started, such as the ServiceManager process, which is started by the fork+execve system call

2.2.1Load the startup configuration of Zygote

${ro.zygote}.rc import /init. rc, init.zygoteXX,XX means 32 or 64, no difference to us we just look at init.zygote32.rc. The configuration file is quite long, so this is an interception to preserve the Zygot related parts.

service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server    
class main    
socket zygote stream 660 root system    
onrestart write /sys/android_power/request_state wake    
onrestart write /sys/power/state on    
onrestart restart audioserver    
writepid /dev/cpuset/foreground/tasks
Copy the code
  • Service zygote: is the process name,
  • /system/bin/app_process: path of executable program, used for init process fork, execve call
  • -xzygote /system/bin –zygote –start-system-server is its parameter

2.2.2Start the process

There are two ways to start a process:

First: fork+handle

pid_t pid = fork();
if (pid == 0) {// child process
} else {
  // parent process
}
Copy the code

Second: fork+execve

pid_t pid = fork();
if (pid == 0) {
  // child process
  execve(path, argv, env);
} else {
  // parent process
}
Copy the code

They both look similar. First, the child process is created by calling the fork function, which returns twice, once for the child and once for the parent. The difference is:

  • The pid returned by the child process is 0, but the PID returned by the parent process is the PID of the child process. Therefore, you can distinguish the child process from the parent process according to the PID
  • By default, handle inherits all of the parent’s resources from the child, but when the binary is loaded through execve, the parent’s resources are erased

2.2.3Signal processing -SIGCHLD

When a parent forks a child, the parent needs to pay attention to this signal. When the child dies, the parent receives SIGCHLD and can do some processing. For example, if the Zygote process hangs, the parent init process will be signaled to restart the Zygote process.

3. Zygote process startup principle

It is mainly divided into two parts: Native layer processing and Java layer processing. After Zygote process starts, it executes execve system call. It executes main function in binary executable program written in C++ as entry, and then runs in Java layer!

Let’s take a look at the processing flow of Native layer

In app_main. CPP file, androidRuntime. CPP file. We can find several main function names

int main(int argc,char *argv[]){
	JavaVM *jvm;
	JNIEnv *env;
	JNI_CreateJavaVM(&jvm,(void**)&env,&vm_args); // Create a Java VM
	jclass clazz = env->FindClass("ZygoteInit"); // Find a Java class called ZygoteInit
	jmethodID method = env->GetStaticMethodID(clazz,"Main"."[Ljava/lang/String;)V"); // Find the static function of Main in the ZygoteInit class
	env->CallStaticVoidMethod(clazz,method,args); // Call main
	jvm->DestroyJavaVM(a); }Copy the code

Based on the above code, you will find that JNI calls can be made directly in our application without the need to create virtual machines. Since the application process is incubated by the Zygote process, the virtual machine that inherits the parent process only needs to reset the data.

Next, take a look at the Java layer processing, as shown in the main method of the ZygoteInit file

  1. Preload resources, such as common class libraries, theme resources, and some shared libraries

  1. Start the SystemServer process

  1. Into the Socket of the Loop cycle will see ZygoteServer. RunSelectLoop (…). call
boolean runOnce(a) {
	String[] args = readArgumentList(); // Read the parameter list
	int pid = Zygote.forkAndSpecialize(); // Start the child process based on the parameters read
	if(pid == 0) {
		//in child
		// Execute the entry function for ActivityThread (main)handleChildProc(args,...) ;return true; }}Copy the code

Four,

The Zygote startup process requires the following two problems

  1. Zygote fork is guaranteed to be single-threaded
  2. Zygote IPC uses sockets

Three things to watch ❤️

If you find this post helpful, give it a thumbs up.