1. Traditional Linux interprocess communication

1.1. Fundamentals

[Process isolation]

Memory is not shared between processes. If data is to be exchanged, a special communication mechanism is used: interprocess communication (IPC).

[Process space division]

To protect User processes from directly operating the Kernel and ensure Kernel security, the operating system logically divides the virtual Space into User Space and Kernel Space.

[System call]

User space requires access to resources in kernel space, such as file operations, network access, and so on. The only way to do that is through a system call. Ensure that all resource access is under the control of the kernel, improve system security and stability.

  • When a process executes a system call and is trapped in kernel code, it is in kernel running state (kernel-state).
  • When a process is executing the user’s own code, it is in user-run mode (user-run mode).

System calls are mainly implemented through the following two functions:

copy_from_user() // Copy data from user space to kernel space
copy_to_user()   // Copy data from kernel space to user space
Copy the code

1.2. Principle of pipes and message queues

[Process steps]

  1. The sending process will send data stored in the memory cache, through the system call into the kernel state.
  2. The kernel program creates a kernel cache in kernel space, calledcopy_from_user()Function copies data from the memory cache of user space to the kernel cache of kernel space.
  3. When receiving data, the receiving process creates a memory cache in its own user space, which the kernel program callscopy_to_user()Function copies data from the kernel cache to the receiving process’s memory cache.

“Defect”

  1. Poor performance, one data transfer requires two data copies: memory cache –> kernel cache –> memory cache.
  2. The receiving process does not know the size of the received data, so it can only make as much memory space as possible (wasted space) or call the API to receive the message header first to get the size of the message body (wasted time).

2. The principle of Binder

2.1. What is Binder

  • From the perspective of interprocess communication, a Binder is a mechanism for interprocess communication.

  • From a Server process perspective, Binder refers to a Binder entity object in Server.

  • From a Client process perspective, a Binder refers to a remote proxy of a Binder entity object.

  • From a transport point of view, a Binder is an object that can be transferred across processes. Binder drivers automatically convert proxy objects to local objects with a little special treatment for objects that cross process boundaries.

2.2. Dynamic Kernel Loadable Module (LKM)

  • A kernel module is a self-contained program that can be compiled separately but cannot be run independently.
  • Kernel modules are linked to the kernel at run time and run as part of the kernel.
  • You can dynamically add a kernel module running in kernel space.

Because Binder is not part of the Liunx kernel, The Binder driver (Binder Dirver) serves as a bridge between user processes.

2.3. Memory Mapping (MMAP)

  • Maps a memory region of user space to kernel space.
  • After the mapping relationship is established, the modification of the memory region in user space can be directly reflected in the kernel space. Conversely, changes made by the kernel space to the memory area can be directly reflected in the user space.
  • Reduce the number of data copies (only needed once) to achieve efficient interaction between user space and kernel space.

2.4. Principle of data transfer with Binder

  1. Binder drivers create a data receive cache in kernel space.
  2. Establish the mapping relationship between kernel cache and data receiving cache, and the mapping relationship between data receiving cache and user space address of receiving process.
  3. The sender process makes a system callcopy_from_user()Copy the data to the kernel cache.
  4. Due to the mapping relationship between the kernel cache and the user space address of the receiving process (which is also mapped into the receiving cache created by Binder), the user space address of the receiving process is also sent, that is, cross-process communication is realized.

2.5. Binder versus traditional IPC

2.5.1. Traditional Linux cross-process

  • [Pipeline] A page size memory is allocated at creation time, and the cache size is limited.
  • [Message queue] Information is copied twice, extra CPU consumption; Not suitable for frequent or informative communication.
  • [Shared memory] No replication, shared buffer directly attached to the process virtual address space, fast; However, the synchronization problem between processes cannot be realized by the operating system and must be solved by each process using the synchronization tool.
  • Socket As a more general interface, low transmission efficiency, mainly used for communication between different machines or across networks.
  • Semaphore Is often used as a locking mechanism to prevent other processes from accessing a shared resource while one process is accessing the same resource. Therefore, it is mainly used as a means of synchronization between processes and between different threads within the same process.
  • [Signal] not suitable for information exchange, more suitable for process interrupt control, such as illegal memory access, killing a process, etc.

2.5.2. Advantages of Binder

  • [High performance] In terms of data copy times, Binder only needs one memory copy, while pipes, message queues and sockets all need two times. Shared memory does not need to be copied. Binder has the second highest performance after shared memory.
  • [Stability] Shared memory has better performance than Binder, so why not use shared memory? Because shared memory needs to deal with concurrent synchronization problems, responsible control, prone to deadlock and resource competition, and poor stability. Binder, on the other hand, is based on C/S architecture, providing independent client and server for high stability.
  • [Security] We know that Android assigns a UID to each application, which is used as an important marker to identify processes. Android also relies on this UID to manage permissions internally, including fixed permissions before 6.0 and dynamic permissions after 6.0. Traditional IPC can only be filled by the user into the packet UID/PID, which is completely controlled in the user space, not in the kernel space, so it is possible to be maliciously tampered, so Binder has higher security.

3. Binder communication model

A complete IPC contains at least two processes, the Client process and the Server process.

3.1. Client/Server/ServiceManager/Binder Dirver

“Relationship”

  • Client, Server, and Service Manager run in user space, Binder drivers run in kernel space.
  • The Client, Server, and ServiceManager are invoked by the systemopen,mmapioctlTo access the device file /dev/binder for indirect cross-process communication.
  • Service Manager and Binder drivers are provided by the system, and Client and Server are implemented by application programs.

【 function 】

  • Binder Dirver: Similar to a router, responsible for the establishment of Binder communication, Binder delivery, Binder reference count management, packet delivery and interaction and other low-level support.
  • ServiceManager: Similar to DNS, it translates a Binder name as a character into a Client reference to the Binder, enabling the Client to obtain a reference to a Binder entity using the Binder name.
  • Client: Gets a reference to real name Binder.

3.2. Communication process with Binder

1. Create a ServiceManager.

To become a ServiceManager, the ServiceManager process must register with the Binder driver, but the entire IPC mechanism has not been established. So the ServiceManager process uses the BINDER_SET_CONTEXT_MGR command, and Binder drivers automatically create Binder entities for it (reference 0), Future Server processes must communicate with the ServiceManager’s Binder through this 0 reference.

2. Register the Server process:

A Server process registers a Binder (Binder entity in a Server) with a ServiceManager using a Binder driver to provide external services. The Binder driver creates entity nodes in the kernel for the Binder and references to the entity by the ServiceManager, packages the name and the new reference to the ServiceManager, and the ServiceManger fills it in the lookup table.

3. The Client process establishes a connection:

Client processes obtain references to Binder entities from ServiceManager using the Server process name and with the help of Binder drivers, and communicate with Server processes through this reference.

4. Data Communication

The Server process copies data to the kernel cache through the system call copy_from_user(), and the Client process can directly use the data in the kernel cache through two layers of memory mapping.


4. Binder principle steps