The previous Android (Java) Learning Note 159 mentions that the Dalvik virtual machine initiates the initialization process, which is the start of the zygote process:
The zygote process is the parent process of all APK application processes : each time an Android application is executed,Zygote will hatch a sub-thread to execute the application (the internal execution of the DVZ command is completed)
Å Special Note: The system provides a app_process process that automatically launches Zygoteinit.java and Systemserver.java two classes, and theapp_process process is essentially using DALVIKVM to start Zygoteinit.java. and loads most of the classes and resources in the framework after it is started.
zygote Process START process:
(1) Configure the zygote startup parameters in Init.rc:
I nit.rc exists in the root directory of the device, the reader can use the ADB pull/init.rc ~/desktop command to remove the file, the file and the zygote related configuration information as follows:
- Service Zygote/system/bin/app_process-xzygote
/system/bin--zygote--start-system-server
- Socket zygote Stream 666
- Onrestart Write/sys/android_power/request_state Wake
- Onrestart Write/sys/power/state on
- Onrestart Restart Media
- Onrestart Restart NETD
The first line uses the service directive to tell the operating system to add the Zygote program to the system service, and the service syntax is as follows:
- The path of the service Service_Name executable executes the list of parameters required by the program itself
The list of parameters required by the service service_name executable program 's path executor itself
The service here is defined as zygote, in theory the name of the service can be arbitrary. The path to the executable is exactly/system/bin/app_process, which is the previously mentioned app_process, with a total of four parameters, respectively, as follows:
-xzygote, this parameter will be used as the parameter that is required when the virtual machine is started , when JNI_CREATEJAVAVM () is called in the STARTVM () function of the AndroidRuntime.cpp class.
/system/bin, which represents the directory where the virtual machine program is located , because app_process can completely not be in the same directory as the virtual machine, while the APP_ Within the Androidruntime class inside the process, you need to know the directory where the virtual machine resides.
--zygote, which indicates the Zygoteinit class as the virtual machine execution of the portal , if there is no--zygote parameter, you need to explicitly specify the class name to execute.
--start-system-serveris only valid when the--zygote parameter is specified, meaning that the first process systemserver is hatched after the Zygoteinit is started.
The next configuration command socket is used to specify the socket used by the service, followed by the name, type, and port address.
The onrestart command Specifies the condition that the service restarts, that is, when these conditions are met, the Zygote service requires a restart, which is typically a system exception condition.
(2) Start the socket service port
When the zygote service starts from App_process, a Dalvik virtual machine is started, and the first Java class executed by the virtual machine is Zygoteinit.java, so the next procedure starts with the main () function of the Zygoteinit class. The first important thing to do in the main () function is to start a socket service port, which is used to receive commands to start a new process.
(3) Load preload-classes
In the main () function of the Zygoteinit class, the new process cannot be hatched immediately after the socket server is created, since the "nucleic acid" is not required for this "egg", which refers to most of the pre-assembled framework classes and resources. the preinstalled class list is a list of text files in Framework.jar, with the name Preload-classes, and the original definition of the list in the frameworks/base/preload-classes text file. And the file was passed Frameworks/base/tools/preload/
(4) Load preload-resources
Preload-resources is in frameworks/base/core/res/res/values/. Defined in Arrays.xml, contains two types of resources, one for drawable resources and one for color resources, as shown in the following code:
- <array name="Preloaded_drawables">
- <item> @drawable/sym_def_app_icon</Item>
- ... ...
- </Array>
- <array name="preloaded_color_state_lists">
- <item> @color/hint_foreground_dark</Item>
- ... ...
- </Array>
Loading these resources is done in the preloadresources () function, which calls Preloaddrawables () and preloadcolorstatelists () to load the two types of resources, respectively. The principle of loading is simply to read these resources into a global variable that will persist as long as the class object is not destroyed.
The global variable that holds the drawable resource is mresources, and the type of the variable is the resources class, because the class internally holds a list of drawable resources, so actually caching these drawable resources is within The global variable that holds the color resource is also mresources, and within the resources class there is also a list of color resources.
(5) Start a new process with folk
Folk is a system call to a Linux system that replicates the current process and produces a new process. The new process will have exactly the same process information as the original process, except for the process ID. The process information includes the file description list characters that the process opened, the allocated memory, and so on. When the new process is created, two processes will share the allocated memory space until one of them needs to write to the memory, the operating system is responsible for copying a copy of the destination address space, and will write the data to the new address, this is called the Copy-on-write mechanism, that is, " Copy only when writing, this mechanism maximizes the sharing of physical memory across multiple processes.
For the first time, readers of folk may find it strange, why copy the process? In a familiar Windows operating system, an application typically corresponds to a process, and if you are copying a process, the possible result is a copy of an Office program from the calculator program, which sounds unreasonable. To replicate a process immediately, you need to first understand the process's startup process.
In all operating systems, there is a program loader, which typically acts as part of the operating system and is called by the so-called shell program. When the kernel is booted, the shell program starts first. The common shell program contains two categories, one is the command line interface, the other is the window interface, the Windows System Shell program is the desktop program, Ubuntu System shell program is the GNOME desktop program. After the shell program starts, the user can double-click the desktop icon to launch the specified application, and within the operating system, starting a new process contains three procedures.
The first procedure, the kernel creates a process data structure that represents the process that will be started.
The second procedure, the kernel Invoker loader function , reads the program code from the specified program file and loads the program code into the pre-set memory address.
The third procedure, after loading, the kernel points the program pointer to the entrance of the target program's address to start executing the specified process. Of course, the actual process will take into account more details, but the general idea is so simple.
In general, it is not necessary to replicate a process, but rather to create a new process from the three procedures above, but it is recommended to use the replication process when the following conditions are met: that is, two processes share a large number of programs.
For example, go to Australia to see kangaroos and go to Australia to see koalas, this is two processes, but the completion of the two processes are the most tasks are the same, that is, the first booking tickets, then take the camera, then take the subway to the capital airport, and finally 14 hours of flight to Australia, then the only difference is to see koalas and kangaroos. In order to do these two tasks more effectively, you can hire an elf process, let it book tickets, take the cameras, take the subway, fly, all the way to Australia, from this wizard process to replicate two processes, one to see the koala, the other to see the kangaroo. If you want, you can also go to the Sydney Opera House, which is the replication of the process, and the benefit is that it saves a lot of shared memory.
Since the folk () function is a system call to Linux, the Java layer in Android is simply a JNI encapsulation of the call, so the next step is to introduce the use of the folk () function in a section of C code so that you can have a more specific understanding of the function:
/** *FILENAME:MYFOLK.C*/#include<sys/types.h>#include<unistd.h>intMain () {pid_t pid; printf ("pid =%d, take camera, by subway, take air! \ n", Getpid ()); PID=folk (); if(PID >0) {printf ("pid=%d, I'm a genie! \ n", Getpid ()); PID=folk (); if(!pid) printf ("pid=%d, go see the Koala! \ n", Getpid ()); } Else if(!pid) printf ("pid=%d, go see the kangaroo! \ n", Getpid ()); Else if(PID = =-1) Perror ("Folk"); GetChar (); }
The above code executes the following results:
$./myfolk.bin 3927, take camera, by subway, take air! pid=3927, I am the elf! pid=3929, go to see the kangaroo! pid=3930, go to see Koalas!
The return value of the folk () function is completely different from the normal function call. When the return value is greater than 0 o'clock, the parent process is represented , and when it equals 0 o'clock, the process being copied is represented . In other words, the code for both the parent and child processes is in the C file, except that different processes execute different code, and the process is differentiated by the return value of folk ().
As can be seen from the above implementation results, the first call to folk () copied a "Look at the Kangaroo" process, and then in the parent process again called folk () copied the "See Koala" process, all three have their own different process ID.
The zygote process is the "sprite process" in this example, where "take a camera, take a subway, take a plane" is the function of the Preload-classes class loaded in the zygote process.
Copying a new process in Zygoteinit.java is done by calling the RunOnce () function of the Zygoteconnection class in the Runselectloopmode () function, and the function calls the following code to replicate a new process.
The Forkandspecialize () function is a native function, and its internal execution is similar to the C code above.
After the new process has been created, some "aftercare" work is needed. Because when zygote replicates a new process, it has created a socket server that should not be used by the new process, or there will be multiple processes in the system that receive the socket client's commands. Therefore, after the new process is created, you first need to close the socket server in the new process and invoke the main () function of the class file specified in the new process as the entry point for the new process. This is done after calling the Forkandspecialize () function based on the return value PID, as shown in the following code:
PID equals 0 o'clock, which represents the sub-process, the key code in the Handlechildproc () function is as follows, first about the socket server.
The execution begins at the main () function of the specified class file, as shown in the following code:
At this point, the new process is completely out of the zygote process of the incubation process, become a real application process.
Android (Java) Learning Note 160:framework start of the operating environment zygote