Introduction to the

How Android implements cross-process communication, what Binder is familiar with, how to design, how to send and receive data between processes. This paper will analyze and summarize the Binder driver implementation, Native layer implementation and Java layer implementation.

Binder learning ideas

  1. Differences between Binder and traditional IPC
  2. Binder driven internal design, data structure
  3. Binder drives the communication process between application processes (C/S)
  4. The process by which Android applications communicate with Binder drivers
  5. How Android Developers communicate with Binder (AIDL, Java Layer Architecture)

Basic knowledge understanding

  1. The Unix kernel and application processes use separate physical memory, with the kernel using 1 gigabyte of physical memory and other applications having their own 3 gigabytes of physical memory (32-bit operating systems)
  2. Because the physical memory of the kernel and the application is separate, data copying is required to transfer data between the two
  3. Memory mapping (MMAP) maps two virtual memory address Spaces (different processes) to the same physical memory segment. Realize a common memory between multiple processes (or kernel and process) to reduce the number of data copies
  4. A Unix driver is a program that runs in kernel mode (using the kernel’s corresponding physical memory)
  5. Binder is also an IPC implementation that differs from traditional Unix IPC (using MMAP)

Understand the existence of Binder drivers

Because of cross-process communication, how data is transferred and organized. Binder drivers solve the problem of how two processes know each other’s identifiers (references). Each process needs to register with the Binder driver to provide services (API calls) to other processes so that the other processes know where their data is going. Ignore the ServiceManager’s special identity for now. Only the positioning of Binder drivers is discussed.

Binder drivers are the backbone of interprocess communication in Android. Binder drivers are the backbone of interprocess communication in Android. There is no coupling between the internal design and the application process. You can understand the relationship between Binder drivers and application processes by using the following figure.

Binder also has ServiceManager as a service.

The existence of ServiceManager

ServiceManager is a system process provided by the Android operating system. This process records information about all Binder entities (Binder implementation objects that provide services).

In other words, SM is used for the application to find other applications of the data center and verification center, to ensure the security of interprocess communication, new, legitimacy.

SM is a system service. After the system is started, SM starts and does the following:

  1. Open Binder drive
  2. Register yourself as a Binder driven butler (other processes can find the corresponding Binder entities according to reference number 0)
  3. Enter the loop and keep reading messages from Binder drivers (no messages blocked)
  4. Process the message after it has been read
  5. The cycle goes on and on and on

SM processes the following types of messages:

  1. Registers with Binder entity objects
  2. Query Binder entity objects as reference numbers back to the query process

When registering Binder entity information to SM, the description information of Binder entity shall be written in the request data, and the corresponding Binder application number shall be obtained according to the description information in the subsequent query.

It can be seen that the Binder architecture is actually a Client, Server and DNS structure. Of course, Binder drivers act as routers.

The premise of this structure is that DNS needs to be pre-registered. This means that SM processes need to be the first to register with Binder drivers. Moreover, both Client and Server know the SM reference number (0) and can directly obtain the Binder reference number provided by other processes through SM

Binder drives the startup process

Open the

  1. Every process that needs to communicate with Binder needs to open the /dev/binder driver once (at most)
  2. After the Binder driver is opened, the kernel calls the binder_open method of the driver, which creates a binder_proc structure inside, storing process information and UID information in memory.

The memory mapping

  1. /dev/binder is memory-mapped using mmap
  2. After the Mmap call, the kernel calls the driver’s binder_mmap method, which internally creates a binder_buffer structure for the process, creating a buffer for the process to receive data. And the inner and buffer pair should have two virtual memory address segments, one is the virtual space of the kernel, one is the virtual space of the process user space. This block buffer is a read-only area that prevents user space from modifying it.

Action performer

For the application process, the opening of the driver and memory mapping actions are performed by the Native class ProcessState, which is simple and takes place in the constructor, opening first, and then performing the memory mapping.

Differences between binders and shared memory

The reason for the comparison with shared memory (performance) is that shared memory tubes are one of the fastest IPC mechanisms in Unix.

The reason why shared memory is fast is that shared memory refers to the virtual address space of two processes to a piece of physical memory. The modification of this memory area by two processes can directly reflect the other process, that is, there is no need to copy data.

Binder works with Mmap, which in theory allows two processes to map to the same physical memory area (file). Binder does not implement this, and if so, shared memory is the same. So how did Binder do that?

First, Binder has drivers through which all data is transferred and received. The problem is that Binder drivers run in kernel mode, so data must be copied between kernel and user memory space.

Imagine that process A communicates with process B, and process A sends data to process B. According to the above analysis, data needs to be copied from user space of process A to the kernel space driven by Binder, and then written to the kernel space driven by Binder. User space of the process B that is finally copied from Binder drive. In this way, the data is copied twice.

In fact, the Binder driver does not need to copy data twice because Binder maps the kernel memory space to the user memory space, as shown in the following figure

First, we can see from the data receiving process that the kernel and user memory space are mapped to the same physical memory through Mmap. This means that changes to this block of physical memory will be withdrawn to user space and kernel space of the data receiving process.

Now the data sending process, the data sending process on the left, just maps the kernel memory space to physical memory.

Then, when the data sending process needs to transmit data to the data receiving process, the data only needs to be copied from the user memory space of the data sending process to the kernel memory space of the data sending process. At this point, because the kernel memory space of the data sending process is mapped to the physical memory, The user memory space of the data receiving process and the kernel memory space are mapped to the same physical memory at the same time, so this copy directly copies the user space data of the data sending process to the user memory space of the data receiving process.

According to the above analysis, it can be understood that a Binder needs to copy data once when transferring data, but shared memory does not need to copy data

Binder implementation architecture

After analyzing the underlying IPC implementation for Binder cross-process communication, you need to think about how Android can connect two processes (how to find communication processes). You need a system process that all applications know about and can contact. From this system process, The ability to find the process to communicate with (via the Service name string).

Finally, Android adopts the architecture of Client, Server, and ServiceManager. The Client needs to find the Server from the ServiceManager, and then the Client can communicate with the Server

So what process can be registered in the ServiceManager, is registered in the Android operating system (APP manifest file Service) that part of the Service can be registered, to this, also can understand why Android uses this architecture mode, further constraints on security.

Binder drive

Binder drivers run in kernel mode, where memory is shared by all processes.

Task 1: Store Binder information for all processes (reference numbers, Server virtual memory addresses)

Task 2: Data transfer between processes

What is the Binder

Binder needs to be interpreted in many ways and represents different things in different environments.

Binder representation in Server

Binder stands for concrete implementation in Server, referred to as the Binder entity

Binder in Client

Binder is implemented by the Server process, which means that the Client process cannot obtain the address information of the Binder. All a Binder represents in a Client is a reference (driver-given) number that a Client can use to send data to a remote Server.

Binder in drivers

Drivers are a core part of the Binder architecture, and they do a lot of work

  1. All Server side Binder entities need to be registered with the driver
  2. When a Client obtains a Binder, it needs to create a Binder reference for the Client and record the reference number information in the driver
  3. Maintains the mapping between the Binder entities in each Client
  4. Find the corresponding entity by reference number
  5. Create Server side Binder entities
  6. Etc…

Binder entities need to be registered with the driver. When registered, the driver needs to create a binder_node structure for Binder entities in the kernel. The main data stored in this structure is

Server side Binder entity object memory address

Server side Binder entities node structures in all entity linked lists

Each Server process should have a linked list of all Binder entity nodes indexed by the memory address of the Binder entity object.

A Binder reference (Client) is expressed in a driver

A Binder reference exists in the driver as a binder_ref structure. The main data stored in the modified structure is as follows:

  • Structure reference of Binder entities in drivers
  • Reference number of Binder entities in drivers
  • Binder references nodes in process lists (two linked list nodes indexed by number and entity address)

Note: Each Client process should have two linked lists, one indexed by the Binder entities in the driver structure address, and one indexed by the Binder entities in the driver reference number of the linked list.

A representation of Binder in the transmission of data

Both Binder entities and Binder references are identified by different structures in the driver, but Client and Server do not represent different binders by passing these two structures to each other when the Binder communicates. Instead, another unified structure, flat_binder_object, represents the corresponding Binder for this communication.

Since we are using the same structure, what should be in this structure:

  • Binder types (entities, references)
  • Memory address of Binder entities (for entities)
  • Binder Application number (for reference)

Binder types are as follows:

  • BINDER_TYPE_BINDER: A Binder entity is passed and references to that entity are strongly typed;
  • BINDER_TYPE_WEAK_BINDER: Indicates that a Binder entity is passed and references to that entity are weak types;
  • BINDER_TYPE_HANDLE: Indicates that a Binder strongly typed reference is passed
  • BINDER_TYPE_WEAK_HANDLE: A reference to a Binder weak type is passed
  • BINDER_TYPE_FD: Binder passed as a file

The Server sends the flat_binder_object with type BINDER_TYPE_BINDER to the Client. For example, the Server sends the flat_binder_object with type BINDER_TYPE_BINDER. The driver creates the corresponding binder_node structure for the Server process in the kernel and stores the memory address of the Binder entities in flat_binder_object. Binder_ref = binder_ref = binder_ref = binder_ref = binder_ref = binder_ref = binder_ref = binder_ref = binder_ref This number is stored in the binder_ref structure. You also need to change the type in flat_binder_object to BINDER_TYPE_HANDLE and store the reference number.

When the Client needs to use the Binder delivered from the Server, the reference number of Binder is needed in the data packet delivered to the driver. The driver will verify the reference number, so that the security can be guaranteed.

Binder Presentation Summary

When a Server process creates a Binder entity, the entity is expressed in various environments as follows

  1. Binders in Server processes are called Binder entities that should inherit from the BBinder class (Native class).
  2. This is expressed in Binder drivers as binder_node
  3. The Binder driver creates a binder_ref structure when the Binder services of the Server process need to be used by the Client process. This is the representation of the Binder entities created in the Server process in the Client process (storage reference number).
  4. In the Client user space, a Binder proxy class needs to be created, which inherits the BpBinder class. The Client process communicates with the Binder entities on the Server side through this proxy class