1. The zygote process.
Fork from the init process.
Zygote has two main functions, starting the SystemServer process and forking child processes. WMS, AMS, PMS, etc. all run in systemServer processes. Our normal app process is fork by Zygote.
Why does Zygote need a single thread when forking child threads?
Fork is based on copy-on-write. The ZYgote process has started the JVM, class preloaded resources, and so on. Resources can be inherited from the parent process at fork time. However, fork supports only single threads, not multiple threads. Zygote creates child processes with only one thread, which can cause problems such as deadlocks or resource missyncing. There are many threads in the parent process. When zygote forks a child process, it stops all threads outside the parent’s main thread and waits for the fork process to complete. It is important to note, however, that the Zygote process is not single-threaded, as it has daemon threads to run.
Why not just use SystemServer for incubation
1. From the perspective of architectural design principles, try to achieve the principle of single class or module.
2. From the perspective of function realization. When forked, the child inherits some of the parent’s resources. We need the most preparation when we start a new inheritance. For example, create VMS and load resources. These, if loaded ahead of time, can greatly optimize the process creation process. The systemServer process is mainly used to incubate various sample services and cannot be inherited from child processes. When we start the process, it’s best to be clean, except for the necessary resources. So the system creates a Zygote process. It not only meets the purpose of efficient fork process, but also achieves the single and decoupled module function.
Zygote’s IPC uses sockets, not binders
To avoid deadlocks when forking child threads, a single-threaded environment is required. Binders, on the other hand, are individual threads and are prone to deadlocks when child threads are forked.
2. Binder is cumbersome to call. If Zygote uses Binder to communicate, you need to open the Binder driver, get file descriptors, mMAP memory maps, and create binder objects to the serviceManager. Binder objects are also queried from the serviceManager when invoked. A few back and forth is more troublesome. Zygote and systemServer processes are the parent and child relationship, for this simple message, socket is more convenient.
Zygote uses binder to fork systemServer processes, which inherit zygote’s descriptors and memory maps. The two processes share a common set of data results at the Binder driver layer. Copy-on-write of the child causes the address space to be remapped. However, the child process still accesses the mmap address of the previous parent process, resulting in SIGSEGV and SEGV_MAPERR errors
2. Start the Android system
The overall startup of Android system is quite complicated. The main nodes can be briefly described as. 1. The init process forks out the Zygote process. Zygote forks the SystemServer process and other child processes using the runOnce method. Systemserver starts with the startSystemServer() method. Binder is started with the nativeZygoteInit() method. Then call systemServer’s main function. The main function has the following functions.
private void run(){
Looper.prepareMainLooper();
System.loadLibrary("system_service");
createSystemContext();
startBootStrapService();
startCoreService();
startOtherService();
Looper.loop();
}
Copy the code
How system services are published:
PublishBinderService (String name,IBinder Service) registers the service with the serviceManager
What thread does the system service run on:
DisplayThead, fgThread IoThread, UIThread (here the UIThread child thread), binder threads
How the interdependencies between services are resolved:
Batch startup: For example, AMS, PMS startup in phases: Different services are started in different phases
Start the desktop
Finally, call the systemReady() method to start the launcher with startHomeActivityLocked
3. Differences between system services and BIND services
The specific type | System services | The bind service |
---|---|---|
Start the way | StartBootStrapService () in the ststemService process; startCoreService(); startOtherService(); In the start | StartService (Intent Intent),classLoader loads the class, and then creates the context |
Registration way | Public static void addService(String name,IBInder Service){getServiceManager().addService(name,service,false)} | Binder service to AMS |
Registered location | Registered to serviceManager | Registered with the AMS |
Registration time | (1) systemService (Java) (2) SurfaceFlinger (jNI | Manually register |
use | context.getSystemService(Context.POWER_SERVICE) | binderService(serviceIntent,ServiceConnection) |
4. Process & Binder start
The diagram shows the app’s cold startup process. The startup core of the app is still Zygote. Binder communication is an inescapable point in the startup process.
The application notifies AMS that it has passed when it has startedbinderNotify by correspondence. Binder starts at ZygoteStart the processFrom time to time. Zygote calls the runOnce function when it receives an AMS startup request
boolean runOnce(){
Stringargs=readArgumentList(); int pid=Zygote.forkAndSpecialize(...) ;if(pid==0){
handleChildProc();
return true;
}else {
// deal parentProc }}Copy the code
Binder is started in nativeZygoteInit() in handleChildProc(). Binder startup is divided into four main steps
- Open binder drive
- Map memory and allocate buffers
- Register binder threads
- Enter the binder loop
5.Application
Generally used:
- Save global application variables
- Initialization operation
- Provide context
Initialization: Follow up from main
public static void main(String[] args){
Looper.prepareMainLooper();
ActivityThread thread=new ActivityThread();// Just a normal Java class, not thread
thread.attach(false);
Looper.loop();
}
Copy the code
Called in the attach function
private void attach(){
final IActivityManager mgr=ActivityManagerNative.getDefault();//AMS is the binder proxy object for the application process
mgr.attachApplication(mAppthread);//mAppthread is a binder object for application processes that is passed into AMS
}
Copy the code
The function is then called in ASM
boolean attachApplicationLocked(IApplicationThread thread){
thread.bindApplication();//IPC communicates to the application process
}
Copy the code
The bindApplication function of the application process is
public final voidBindApplication () {AppBindData data=new AppBindData();
sendMessage(H.BIND_APPLICATION,data);// Throw it to the main application thread
}
Copy the code
In the main thread to create the Application object and call the mInstrumentatio. CallApplicationOnCreate (app);