An overview of the

Recently, I have been learning the Binder mechanism. I have read a lot of information on the Internet, and I have also read The blogs of Binder series by Luo Luo and Innost, which are all about C code from the bottom. Although I have learned C and C++ before, However, the fancy jump between various functions, I have doubts about life. It is no exaggeration to say that every time I read it, I will read it again. And then I saw Gityuan’s blog and I saw some illustrations and it was like discovering a new continent.

P6P7 android advanced information sharing

The following is a graphical introduction to Binder mechanisms that you will find useful in this article.

Binder process communication principle video details need password private chat I can link: share.weiyun.com/5GOZsQF

What is a Binder?

Binder is one of the most important features of Android as a means of interprocess communication (IPC). The four components of Android, Activity, Service, Broadcast, ContentProvider, and different apps, all run in different processes. It serves as a bridge for communication between these processes. As its name suggests, it is the glue that binds the components of a system together, serving as a bridge between them.

Understanding Binder is crucial to understanding the Android system as a whole, and it is difficult to gain a deeper understanding of the Android system without understanding Binder.

1. The Binder architecture

  • Binder communication uses the C/S architecture and consists of Client, Server, ServiceManager, and Binder drivers from a component perspective. The ServiceManager manages various services in the system.

  • Binder is encapsulated in the Framework layer, invoking the Native (C/C++) layer’s Binder architecture through JNI technology.

  • Binder communicates with Binder drivers in the Native layer as ioctL.

2. The mechanism of Binder

  • The binder_proc structure, binder_procs, is the binder_procs, binder_procs, binder_procs, binder_procs, binder_procs, binder_procs Todo task queues in each binder_proc structure), and then caches the registered services to the ServiceManager’s SvCINFO list.

  • With the server, the client can communicate with the server. Before communication, the client needs to obtain the service and get the proxy of the service, which can also be understood as a reference. For example:

    WindowManager wm = (WindowManager)getSystemService(getApplication().window_service);Copy the code

    The way to obtain the server is to use the ServiceManager to query the proxy to return the server from the SvCInfo list. The SvCInfo list is the address book of all registered services and stores the information about all registered services.

  • With a server reference we can send a request to the server, send our request parameters to the ServiceManager using BinderProxy, copy our parameters to the kernel space using shared memory using the kernel method copy_from_user(). The Binder driver inserts a transaction into the server’s TODO queue and copies the result of the execution to user space via copy_to_user(). Binder makes only one copy), wakes up the waiting client and responds with the result, thus completing a communication.

These are the main ways Binder mechanisms communicate with each other. Let’s take a look at the implementation.

3. The Binder

Let’s take a look at how user space interacts with kernel space.

Just a few concepts

User space/kernel space

For detailed explanation, refer to Kernel Space Definition. Simple understanding is as follows:

Kernel space is the running space of the Linux Kernel, and User space is the running space of User programs. For security, they are isolated so that even if a user’s program crashes, the kernel is not affected.

Kernel space can execute any command and call all resources of the system. A User space can only perform simple operations and cannot directly call system resources. It must issue instructions to the kernel through the system interface (also known as system Call).

System call/kernel/user mode

Although the user space and kernel space are logically separated; But inevitably, there will always be some user space that needs access to kernel resources; For example, the application accesses files, the network is very common things, how to do?

Kernel space can be accessed by user processes only through the use of system calls.

The only way for user space to access kernel space is through system calls; Through this unified entry interface, all resource access is implemented under the control of the kernel, so as to avoid unauthorized access to system resources by user programs, thus ensuring the security and stability of the system. User software is good and bad, what if they mess with the system and break it? Therefore, certain privileged operations must be handed over to a secure and reliable kernel.

When a task (process) executing a system call is stuck in kernel code, the process is said to be in kernel mode (or kernel-mode for short) when the processor is executing in kernel code with the highest privilege (level 0). When a process is executing the user’s own code, it is said to be in user mode (user mode). That is, the processor is running in the user code with the lowest privilege level (level 3). The processor can only execute privileged CPU instructions when the privilege level is high.

Kernel module/driver

Kernel space is accessible to user space through system calls, so what if one user space wants to communicate with another? The natural thing to think about is having the operating system kernel add support; Traditional Linux communication mechanisms, such as sockets and pipes, are supported by the kernel. But Binder is not part of the Linux kernel, so how does it access kernel space? Linux’s Loadable Kernel Module (LKM) mechanism solves this problem; A module is a self-contained program that can be compiled separately but cannot be run independently. It is linked to the kernel at runtime and runs in kernel space as part of the kernel. In this way, the Android system can communicate with each other by adding a kernel module that runs in the kernel space and acts as a bridge between user processes.

Binder drivers are the kernel modules that run in the Android kernel space and communicate with user processes through Binder.

A Device Driver is a special program that enables a computer to communicate with a Device. Equivalent to the hardware interface, only through this interface, the operating system can control the work of the hardware device;

A driver is the interface that operates the hardware. Binder uses a “hardware” module to support the communication process, so it is called a driver.

With these concepts in mind, binder_open(), binder_mmap(), binder_ioctl() in userspace call methods in kernel space Binder drivers through system calls. The shared memory between kernel space and user space is transferred between user space and kernel space memory by copy_from_user() and copy_to_user() kernel methods. Binder drivers have a global binder_procs linked list that holds server process information.

4. Binder processes and threads

For the underlying Binder drivers, all binder_PROC constructs created are recorded through the binder_procs linked list. Each binder_PROC construct in the Binder driver layer corresponds to a user-space process used for Binder communication. And each process has one and only one ProcessState object, which is guaranteed by the singleton pattern. There can be many threads in each process, and each thread corresponds to one IPCThreadState object. The IPCThreadState object is also a singleton pattern, that is, one thread corresponds to one IPCThreadState object, and has corresponding structure in Binder driver layer. That is the Binder_thread structure. All binder_threads in the current process are recorded using the rb_root threads member in the binder_PROC structure.

Binder thread pool: Each Server process creates a Binder thread pool at startup and registers a Binder thread with it; Server processes can then register new threads with the binder thread pool, or binder drivers can actively register new binder threads with Server processes when they detect that there are no free binder threads. A Server process has a maximum number of Binder threads (16 by default). For example, the Android system_server process has 16 threads. All binder requests to the Client process are handled by the Server process’s binder threads.

5. ServiceManager start

How to communicate with Binder drivers? That is through ServiceManager, a lot of articles say ServiceManager is a Binder driven daemon, the big manager, in fact, ServiceManager is very simple to provide query services and registration services. Let’s take a look at the ServiceManager startup process.

  • The ServiceManager is divided into framework layer and Native layer. The Framework layer encapsulates the Native layer for easy invocation. The figure shows the startup process of the ServiceManager at the Native layer.

  • The ServiceManager is started when the system starts up and the init process parses the init.rc file and calls the main() method entry in service_manager.c. The Native layer has a binder.c that encapsulates methods for interacting with binder drivers.

  • The ServiceManager startup consists of three steps: first, open the driver to create a global linked list binder_procs, then save its current process information to the binder_procs linked list, and finally enable loop to continuously process data in shared memory. And handle BR_xxx commands (BR_xxx commands) with the Binder Reply driver.

6. The ServiceManager registers the service

  • To register the MediaPlayerService server, we use the ServiceManager addService() method to register the service.

  • First the ServiceManager sends BC_TRANSACTION commands (ioctl commands, Binder Client) carries the ADD_SERVICE_TRANSACTION command and the thread that registers the service enters the wait state waitForResponse(). The Binder driver receives a request to add a transaction to the ServiceManager’s TODO queue to register the service. The task of the transaction is to create the server process binder_node information and insert it into the binder_procs linked list.

  • After the transaction is complete, the ServiceManager sends the BR_TRANSACTION command, and after receiving the command, the ServiceManager adds the registered service to the SVCINFO list. Finally, the BR_REPLY command is sent to wake up the waiting thread and notify that the registration is successful.

7. The ServiceManager obtains the service

  • The process of obtaining a service is similar to that of registering, but reversed. The service is registered through the ServiceManager’s getService() method.

  • First the ServiceManager sends the BC_TRANSACTION command to the Binder driver carrying the CHECK_SERVICE_TRANSACTION command, and the thread fetching the service enters the wait state waitForResponse().

  • The Binder driver receives the request and sends BC_TRANSACTION to the ServiceManager to query the registered service and wakes up the waiting thread in BR_REPLY. If the query fails, it communicates with the services in the binder_procs list and responds.

8. Have a full communication

  • With Binder, we basically call methods that are wrapped in the framework. AIDL is a foolproof way of using the framework. Assuming that the service is registered, let’s see how the client executes the server-side methods.

  • First, we obtain the BinderProxy object of the server through ServiceManager. By calling BinderProxy, parameters and method identifiers (for example: TRANSACTION_test, automatically generated in AIDL) passes to the ServiceManager while the client thread enters the wait state.

  • The ServiceManager copies request data such as user-space parameters to the kernel space and inserts a transaction to the server that executes the execution method. When the transaction completes, the ServiceManager is notified to copy the execution result from kernel space to user space, wake up the waiting thread, respond to the result, and the communication ends.

conclusion

All right, this is just a brief introduction to the implementation logic of The Binder mechanism. To understand the Binder mechanism, you have to work hard and read the source code, although the process is painful. A look do not understand again, to tell the truth, I understand the ability is poor, follow the blog ideas to see more than ten times. Hard work always pays off. Enjoy the charm of fancy jumps between native layer methods. In the end you will find a new world opening up to you.

There are a lot of online information, personally feel better as follows:

  1. Bander design and implementation

  2. Android Interprocess Communication (IPC) Binder

  3. In-depth understanding of Innost Binder family

  4. Gityuan Binder series (Based on Android 6.0)

  5. Binder Learning Guide

Binder process communication principle video details need password private chat I can link: share.weiyun.com/5GOZsQF

P6P7 android advanced information sharing