Background knowledge

To better understand Binder, we need to clarify the concepts, since Android is based on the Linux kernel.

Process isolation

Process isolation is designed in order to protect the mutual interference between the operating system process, the process of this technique is to avoid A written process B, process isolation implementation, using the virtual address space, the process of the virtual address of A virtual address and processes of B is different, thus preventing the process A data to process B, between different process between the operating system, Data is not shared. For each process, it is naive to think that it owns the entire system and does not know the existence of other processes. Therefore, a process needs a special way to communicate with other processes

User space/kernel space

The Linux Kernel is the core of the operating system. It is independent of common applications and can access the protected memory space as well as all permissions to access the underlying hardware devices.

For such a high security level as the Kernel, it is obviously not allowed to be called or accessed by other applications. Therefore, it is necessary to provide some protection mechanism for the Kernel. This protection mechanism is used to tell those applications that you can only access certain licensed resources, but not unlicensed resources. Therefore, Kernel and upper layer applications are abstracted separately, called Kernel Space and User Space respectively

System call/kernel/user mode

Although the user space is logically separated from the kernel space, it is inevitable that some user space still needs to access the resources of the kernel space, such as programs accessing files. What to do?

The only way for user space to access the kernel space is system call. Through this unified entrance, all resource access is under the control of the kernel, so as to avoid the unauthorized access of user programs to system resources, thus ensuring the security and stability of the system

When a task process systematic code calls into the kernel code executes, we have the kernel operation of the said process, referred to as the kernel mode, the processor is in a state of the highest privilege levels (0), the kernel code, when the process in the implementation of the user’s own code, referred to in the user state, referred to as “user mode, At this point, the processor is in the lowest privilege state (3), and the processor is in the high privilege state to execute those privileged CPU instructions

Kernel module/driver

Kernel space is accessed by user space through system calls. What if one user space accesses another user space? The first thing that came to mind was to add support through the kernel. Because the kernel is shared, traditional Linux mechanisms like sockets and pipes are supported, but Binder is not part of the Linux kernel. How does it access kernel space? Dynamically loadable kernel module mechanism of Linux solves this problem, the module is an independent function of the program, he can be compiled separately, but cannot run independently, it is link to the kernel at runtime as part of the kernel run in kernel space, in this way, the Android system by adding a kernel module runs in kernel space, This module acts as a bridge between user processes to complete communication.

In Android, the Binder driver is the kernel module that runs in the kernel space and is responsible for user processes’ communication with Binder

A driver is a special program that enables a computer to communicate with a device. It is equivalent to a hardware interface through which the operating system can operate a hardware device

A driver is an interface that operates on hardware. Binder uses hardware to support its communication process, hence the module called a driver.

Why Binder is used

The Linux kernel for Android uses a variety of cross-process communication methods, such as pipes and sockets. There are two main things, efficiency and safety

  • The efficiency of

Socket, as a universal interface, has low transmission efficiency and high overhead. It is mainly used for cross-network process communication. The local communication is slow. The overall effect of two copies of Binder is to make a direct copy of payload data from sender user space to receiver user space, eliminating the kernel staging step and doubling performance. By the way, the Linux kernel doesn’t actually have a function to copy directly from one user space to another. You have to copy copy_from_user() to kernel space and copy_to_user() to another user space. In order to copy user space to user space, memory allocated with mmap() is mapped into the kernel space as well as into the recipient process. So calling copy_from_user() to copy data into kernel space also copies data into the user space of the receiver, which is the ‘secret’ that Binder only needs to copy once.

IPC Number of data copies
The Shared memory 0
Binder 1
Socket/ pipe/message queue 2
  • security

In mobile devices, the extensive use of cross-process communication must put forward strict requirements on the communication system itself. Binder is more efficient than traditional Socket. In addition, traditional process communication does not strictly verify the identity of the communication parties. As long as it is set up on the upper layer protocol, for example, the IP address of Socket communication is manually entered by the client. Android assigns its own UID to each installed application, so a process’s UID is an important indicator of its identity. With traditional IPC, only the user can fill the packet with UID/PID, which is unreliable and easily exploited by malicious programs. Reliable identity tags are only added to the kernel by the IPC mechanism itself.

Based on the above reasons, Android needs to establish a new IPC mechanism to meet the requirements of communication mode, transmission performance and security of the system, namely Binder. Binder Supports both real-name and anonymous BINders, providing high security, and supports only one copy during transmission.

Binder communication model

The four components of Binder mechanism in Android system, Client, Server, ServerManager, and Binder drivers are as follows

  • Client, Server, ServerManager, implement user space, Binder drivers are implemented in kernel space

  • Binder drivers and ServerManager are already implemented on the Android platform, and developers only need to implement their own Client and Server in user space

  • Binder drivers provide device files /dev/binder to interact with user space. Client, Server, ServerManager communicate with Binder drivers through open and IOCtl file manipulation functions.

  • Client and Server processes communicate indirectly through binder drivers

  • ServerManager is a daemon that manages the Server and provides the ability to query the Server as a Client

  • The ServerManager setup starts with a process proposing to the driver as SM. After the driver agrees, SM is responsible for managing the Server, which is now empty

  • Each Server registers with SM. After each Server process starts, it reports to SM, for example, I am Zhangsan, return 0X1234 if you want to find me, and the same is true for other servers. In this way, SM establishes a table corresponding to the name and address of the Server

  • Client wants to communicate with Server, first ask SM, please tell me how to contact Zhangsan, SM returns an address 0X1234 after receiving, Client can communicate with Server after receiving

  • BINDER_SET_CONTEXT_MGR ServerManager provides a special Binder that has no name and does not require registration. Binder drivers automatically create Binder entities for a process that registers itself as SMgr using the BINDER_SET_CONTEXT_MGR command. Second, the Binder reference is fixed to 0 in all clients without any other means of obtaining it. That is, to register a Server with SMgr’s Binder, a Server must communicate with SMgr’s Binder through reference number 0

Client to SM communication, Client to Server communication, Server to SM communication are all driven by the Binder, the driver is unknown, but do the most important work, the driver is the core of the whole communication, so the secret of cross-process communication is hidden in the driver. We’ll talk about that later

Binder mechanism cross-process principle

The communication model of Binder is given above, and four roles of the communication process are pointed out: Client, Server, SM and driver. But we still don’t know exactly how the Client communicates with the Server.

How do two processes A and B, running in user space, communicate? The kernel can access all data of A and B; So, the easiest way to do this is through the kernel; If process A wants to send data to process B, copy the data from process A to the kernel space, and then copy the corresponding data from the kernel space to process B. User space manipulates kernel space through system calls; As it happens, there are two system calls: copy_from_user, copy_to_user.

But that’s not how Binder mechanisms work. The point is that interprocess communication is not a mystery. So how do Binder mechanisms enable cross-process communication?

Binder drives do it all for us.

Suppose the Client process wants to call add, a method on the Server process’s object. For this cross-process communication, let’s look at what the Binder mechanism does. (Communication is a broad concept, and as long as one process can call a method on an object in another process, it’s easy to specify what communication needs to be done.)

First, the Server process is registered with SM; Tell yourself who you are and what you are capable of; In this scenario, the Server tells SM that its name is Zhangsan and it has an object that can be added; So SM creates a table: Zhangsan name corresponds to process Server;

Then the Client queries SM: I need to contact an object in a process named Zhangsan; Here’s the key: The driver does something wrong with the data flow. Instead of returning a real object to the Client process, it returns objectProxy that looks exactly like Object. ObjectProxy also has an add method, but this add method does not have the same ability as the Server process object add method; ObjectProxy’s Add is just a puppet, the only thing it does is wrap the parameters and hand them to the driver. (Here we simplify SM’s process, see below)

But the Client process does not know that the object returned to it by the driver has been tampered with, because it is so disguised as to be true. The Client happily takes the objectProxy object and calls add; As we said, the Add does nothing but wrap the parameters and forward them directly to the Binder driver.

The driver receives the message and finds the objectProxy; I used objectProxy to replace object and send it to Client. What it should really access is the add method of object. The Binder driver tells the Server process, calls your Object add method, and sends the result to me. The Server process receives the message, does so, and returns the result to the driver, which then returns the result to the Client process. So the whole process is complete.

Because the objectProxy returned by the driver is so similar to the original object in the Server process, it seems that the object object in the Server process is directly passed to the Client process. Therefore, Binder objects can be said to be objects that can be passed across processes

But as we know, Binder cross-process transport doesn’t actually transfer an object to another process; The transport process appears to be as if the Binder crosses processes, leaving a body in one process and a shadow (many shadows) in the other. The Client process actually operates on the shadow, which is driven by the Binder to make the real body complete the operation.

This is very important to understand; Be sure to appreciate it carefully. In addition, Android implements this mechanism using the proxy mode, Binder access is directly returned to the original Binder entity if it is in the same process (no cross-process required). If it is in a different process, give it a proxy object (shadow). We can see many implementations of this in the system source code and in the generated AIDL code.

In addition, in order to simplify the whole process, we hide the operation of SM driver. In fact, since THE SM and the Server are usually not in the same process, the Server process’s registration with the SM is also cross-process communication, and the driver can also manipulate this process: The Server object in SM is actually a proxy object. When the Client queries the SM, the driver returns another proxy object to the Client. Sever process has only one local object, all other processes own is its proxy.

To sum up, the Client process is nothing more than a proxy holding the Server side; Proxy objects assist drivers in cross-process communication.

What exactly is a Binder?

Binder Binder on the Server side is no different from Binder on the Client side to the user. A Binder object is all there is to it, regardless of implementation details or even the existence of Binder drivers and SM

1 Generally speaking, Binder refers to a communication mechanism. When WE say AIDL uses Binder to communicate, it refers to the IPC mechanism of Binder

2 For Server processes, Binder refers to Binder native objects

3 For Client processes, Binder is a remote proxy of Binder local objects. The operation of Binder proxy objects is eventually sent to Binder local objects by the driver. For users with Binder objects, It does not care whether a Binder is a proxy or local, and there is no difference between how a proxy object and a local object operate.

4 For transport, Binder is an object that can be delivered across processes. Binder drivers process objects that can be delivered across processes, automatically converting proxy objects to local objects.

Binder drivers We now know that a Binder Server is a local object and a Binder Client is a proxy object. Binder drivers automatically convert these two types of objects when they are delivered across processes. Binder drivers must hold information about each cross-process Binder object. The Binder local object is represented by a data structure called Binder_node. The Binder agent object is a data structure called binder_ref. Binder proxy objects are called binder references. Binder proxy objects are called binder references

Reference:

Blog.csdn.net/luoshengyan…

Blog.csdn.net/universus/a…

Weishu. Me / 2016/01/12 /…