Android Framework cross-process communication IPC 6 - Binder framework

The main content of this article is as follows:

  • 1 Android overall architecture
  • 2 Principle of IPC
  • 3 Introduction to Binder
  • 4 Binder communication mechanism
  • 5 Binder protocol

1. The overall architecture of Android

(1) The overall architecture of Android

In order to let everyone better understand the Binder mechanism, let's first look at the overall architecture of Android. Because in this way everyone knows the status of Binder in the Android architecture. Use the pictures on the official website

img

Android Architecture.png

From bottom to top are:

  • Kernel layer: the Linux kernel and the drivers of various hardware devices. It should be noted here that the Binder IPC driver is also the implementation of this layer, which is quite special.
  • Hardware abstraction layer: encapsulate the "kernel layer" hardware driver, and provide a unified hardware interface that can be called by the "system service layer"
  • System service layer: Provides core services and interfaces that can be called by the "application framework layer"
  • Binder IPC layer: As an IPC bridge between the "system service layer" and the "application framework layer", it transfers the data called by the interface to each other to realize cross-process communication.
  • Application framework layer: This layer can be understood as Android SDK, which provides four major components, basic components used in daily development such as View drawing

(2) Architecture analysis of Android

In a large project, layering is very important. The interface at the bottom is the most "universal", and the granularity of the interface is the finest, and the higher the level, the lower the versatility. Theoretically, each layer above can be "opened" to developers. For example, developers can directly call the interface of the hardware abstraction layer to operate the hardware, or directly call the interface in the system service layer to directly serve the operating system, even like Windows Like development, developers can write programs at the kernel layer and run them in the kernel. However, the problem brought about by openness is that developers have too much power, which is of no benefit to the stability of the system. If a virus creator creates a virus at the kernel layer, the system may never start up. Therefore, Google's approach is to gather the rights of developers to the "application framework layer", and developers can only call the interface of this layer.

In the above layers, both the kernel layer and the hardware abstraction layer are implemented in C/C++, the system service layer is implemented in Java, and the hardware abstraction layer is compiled into a so file, which is used by the system service layer in the form of JNI. The services in the system service layer start with the system startup, and they will keep running as long as the system is not shut down. What are these services for? In fact, it is very simple. It is to complete the core functions of a mobile phone, such as SMS sending and receiving, phone answering, hanging up, application package management, Activity management, etc. Each service runs in an independent process, so it is implemented in Java, so it is essentially running in a Dalvik virtual machine in an independent process. So the question is, the developer's App also runs in an independent process space, if it calls the interface in the service layer of the system? The answer is IPC (Inter-Process Communication). Inter-process communication is different from RPC (Remote Procedure Call), and the implementation principle is also different. Each system service has a corresponding Manager in the application framework layer, which is convenient for developers to call its related functions. The specific relationship is as follows:

img

call relationship.png

(3), to sum up:

  • Android is divided into kernel layer, hardware abstraction layer, system service layer, Binder IPC layer, application framework layer from bottom to top
  • The "application framework layer" in Android is open to developers in the form of SDK. The core services in the "system service layer" run with the system startup, and the Manager provided by the application framework layer provides real-time service calls for applications. Each service in the system service layer runs in its own independent process space, and the Manager in the application framework layer calls the services in the system service layer through Binder IPC.

2. Principle of IPC

Looking at the IPC mechanism from the perspective of the process

img

image.png

Each Android process can only run in the virtual address space owned by its own process. If it is a 32-bit system, it corresponds to a 4GB virtual address space, of which 3GB is user space, 1GB is kernel space, and the size of kernel space It can be configured by parameters. For user space, different processes cannot share each other, but kernel space can indeed be shared. The communication between the Client process and the Server process is precisely to use the shared kernel space between the processes to complete the underlying communication work. The Client and Server processes often use ioctl and other methods to communicate with the driver of the kernel space.

3. Binder overview

(1) Introduction to Binder

1. The origin of Binder

Simply put, Binder is a cross-process communication technology on the Android platform. This technology was not first proposed by Google. Its predecessor was OpenBinder developed by Be Inc, and it was also used in Palm. Later, Dianne Hackborn, the author of OpenBinder, joined Google and was responsible for the development of the Android platform, so he brought this technology into Android.

We know that at the application level of Android, there is basically no concept of process, and at the specific implementation level, after all, it still needs to build processes one by one. In fact, within Android, the components that support the application are often in different inheritance, so the bottom layer of the application will inevitably involve a large number of cross-process communication. In order to ensure the efficiency of communication, Android provides the Binder mechanism.

2. What is Binder

Let's look at Binder from four dimensions, which will make it more helpful for everyone to understand the Binder mechanism

  • 1 From the perspective of classes, Binder is a class of Android, which inherits the IBinder interface
  • 2 From the perspective of IPC, Binder is a cross-process communication method in Android. Binder can also be understood as a virtual physical device. Its device driver is /dev/binder. This communication method is available in Linux None in (Linux does not accept it because the coupling is too strong)
  • 3 From the perspective of Android Framework, Binder is a bridge for ServiceManager to connect various Managers (ActivityManager, WindowManager, etc.) and corresponding ManagerService
  • 4 From the perspective of the Android application layer, Binder is the communication medium between the client and the server. When you bindService, the server will return a Binder object containing the service call of the server. Through this Binder object, the client You can get the services or data provided by the server, where the services include common services and AIDL-based services.

3. Significance of Binder mechanism

The Binder mechanism has two meanings:

  • 1 is a way of inter-process communication (IPC)
  • 2 is a remote procedure call (PRC)

From an implementation point of view, the Binder core is implemented as a Linux driver and runs in kernel mode. Only in this way can it have strong cross-process access capabilities.

4. Compared with the traditional IPC mechanism, why does Google use Binder?

Let's first look at the IPC communication mechanism in Linux:

  • 1. Traditional IPC: anonymous pipe (PIPE), signal (signal), famous pipe (FIFO)
  • 2. AT&T Unix: shared memory, semaphore, message queue
  • 3、BSD Unix:Socket

If you don't know about this, please read the previous article.

Although Android inherits the Linux kernel, the communication mechanism between Linux and Android is different. There are a large number of C/S (Client/Server) application methods in Android, which requires Android to provide an IPC method, and if the process communication method supported by Linux is used, there are two problems: performance and security. That

  • Performance: At present, the IPC supported by Linux includes traditional pipelines, System V IPC (including message queue/shared memory/semaphore) and socket, but only socket supports the communication method of Client/Server, because socket is a common network communication method , its efficiency is low, and the consumption is relatively large (socket connection establishment process and disconnection process have a certain amount of overhead), obviously it is not suitable for large-scale use of sockets on mobile phones. The message queue and pipeline adopt the "store-and-forward" method, that is, the data is first copied from the sender cache to the cache opened by the kernel, and then copied from the kernel cache to the receiver cache, with at least two copy processes. Although shared memory does not need to be copied, it is complicated to control and difficult to use.
  • Security: In terms of security, Android is an open platform with many developers and applications come from a wide range of sources, so it is very important to ensure the security of smart terminals. End users do not want programs downloaded from the Internet to spy on private data without knowing it, connect to the wireless network, and operate the underlying device for a long time, causing the battery to run out quickly. Traditional IPC does not have any security measures and relies entirely on upper-layer protocols to report. First of all, the recipient of traditional IPC cannot obtain the reliable UID/PID (user ID/process ID) of the other party's process, so that it cannot identify the other party's identity. Android assigns its own UID to each installed application, so the UID of the process is an important symbol for identifying the identity of the process. Using traditional IPC, only the user can fill in the UID/PID in the data packet, but this is unreliable and easy to be used by malicious programs. Reliable identity tokens are only added in the kernel by the IPC mechanism itself. Secondly, traditional IPC access points are open, and private channels cannot be established. For example, named pipes, key values ​​of system V, socket ip addresses or file names are all open. As long as programs that know these access points can establish connections with each other, no matter what, malicious programs cannot be prevented from obtaining connections through the recipient address. .

Based on the above reasons, Android needs to establish a new IPC mechanism to meet the system's requirements for communication methods, transmission performance and security, so there is Binder. Binder is based on the Client/Server communication mode. Only one copy is required during the transmission process, and the UID/PID identity is added for sending. The real-name Binder of chicken wings also supports anonymous Binder, which has high security. The following figure is an example of the Binder communication process:

img

Binder communication process.png

  • Compared with the traditional means of cross-process communication, both sides of the communication must deal with issues such as thread synchronization and memory management. The workload is heavy and there are many problems, just like the traditional IPC named pipe (FIFO) semaphore (semaphore) message we introduced earlier. The queue has been removed from Android. Compared with other IPCs, Socket is a relatively mature means of communication, and synchronization control is also easy to implement. Socket is very suitable for network communication, but it is very inefficient for inter-process communication.
  • In terms of architecture, Android has always hoped to blur the concept of process and replace it with the concept of component. The application does not need to care about the location where the component is stored, the process in which the component runs, and the life cycle of the component. Anytime, anywhere, as long as you have a Binder object, you can use the functions of the component. Binder is like a net that organizes the components of the entire system across processes and threads.

Binder is the center of the operation of the entire system. Android uses shared memory to transfer data between processes, so that data only needs to be copied once to reach another city from one process (as mentioned in the previous article, generally IPC requires two steps, the first step is to copy the user process to the kernel , the second step is to copy from the kernel to the service process.)

PS: In the entire Androdi system architecture, although the Binder mechanism is widely used as the IPC (inter-process communication) method, there are also some other IPC methods, such as the Zygote communication that uses sockets.

5. The role of Binder in Service service

In Android, many services communicate through Binder, such as many services under the name of MediaService:

  • AudioFlinger audio core service
  • AudioPolicyService: important services related to audio policies
  • MediaPlayerService: an important service in the multimedia system
  • CarmeraService: An important service related to video/photographing

How is it applied or what is the communication mechanism? So let's take a closer look

(2), summary

Android Binder is a custom implementation on OpenBinder. The original OpenBinder framework is no longer developed, so it can be said that Android has reborn the original OpenBinder. Binder is an IPC (Inter-process communication, inter-process communication) mechanism widely used on Android. Whether it is an application's request for system services, or the application's own external services, Binder is required.

Overall structure

img

Overall Architecture.png

As can be seen from the figure, the implementation of Binder is divided into these layers. According to the big framework, it is

  • framework layer
    • java layer
    • jni layer
    • native/ C++ layer
  • linux driver layer c language

Let's take a closer look.

  • Among them, the Linux driver layer is located in the Linux kernel, which provides functions such as data transmission at the bottom, object marking, thread management, and process control through calls. The driver layer is actually the core of the Binder mechanism.
  • The Framework layer is based on the Linux driver layer and provides the infrastructure for application development. The Framework layer includes both the implementation of the C++ part and the implementation of the basic part of Java. In order to reuse the implementation of C++ to the Java side, it is connected through JNI in the middle.

Developers can use the mechanism provided by Binder on the Framework to develop specific business logic. In fact, not only third-party developers, but also many system services in the Android system are developed based on the Binder framework. Among them, the Binder framework is a typical C/S architecture. So in the following, we call the requester of the service Client and the implementer of the service Server. Clinet's request to the Server will be passed from top to bottom to the kernel's Binder driver through the Binder driver framework, and the request contains the commands and parameters that the Client will call. After the request arrives at the Binder driver, after the provider of the service is determined, the request is passed to the specific service from bottom to top. As shown below:

img

Binder calls.png

If you have some understanding of network protocols, you will actually find that the entire data transfer process is so similar to network protocols.

Four, Binder communication mechanism

Android internally adopts C/S architecture. The Binder communication also uses the C/S architecture. Then let's take a look at the process of Binder in C/S.

(1) The process of Binder in C/S

As shown below

img

Binder process.png

The specific process is as follows:

  • 1. The corresponding Service needs to register the service. Service is the owner of many services. When it wants to provide services to Client, it must first go to Service Manager (hereinafter abbreviated as SM) to register its own service. Server can register one or more services with SM.
  • 2. Client applies for service. As a user of Service, Client has to apply to SM for the service he needs when he wants to use the service. Client can apply for one or more services.
  • 3. When the client successfully applies for the service, the client can use the service.

On the one hand, SM manages the services provided by the Server, and at the same time responds to the client's request and assigns the corresponding service to it. Playing the role is equivalent to Yuelao, frontline on both sides. The advantage of this communication method is: on the one hand, service and client requests are easy to manage, on the other hand, only need to establish a connection to the server for the client during application development, so it only takes a little time to implement The corresponding function of Server. So what does Binder have to do with this communication? In fact, the communication method of the three is the Binder mechanism (for example, the Server registers the service with the SM and uses the Binder communication; the Client application request is also the Binder communication.)

PS: Note that the ServiceManager here refers to the ServiceManager (C++) of the Nativie layer, not the ServiceManager (Java) of the framework layer. ServiceManager is the steward of the entire Binder communication mechanism and the daemon process of the Android inter-process communication mechanism.

(2) The overall framework of Binder communication

Let me tell you in advance here, we will continue to mention two concepts later, one is Server, and the other is Service, I will emphasize here first, Server is Server, Service is Service, please don’t confuse, one Server is below There may be many Services, but a Servcie can only belong to one Server. Below we will look at the Binder framework from three perspectives, so

1. From the perspective of kernel and user space

The Binder communication model is as follows:

img

Binder communication overall framework.png

we can find out that:

  • 1. Client and Server exist in user space
  • 2. The communication between Client and Server is implemented by the Binder driver in the kernel
  • 3. As a daemon process, SM handles client requests and manages all services

If you don't understand the meaning above, we can understand SM as a DNS server , then Binder Driver is equivalent to the routing function. Here is how the Client and Server communicate.

2. From the perspective of Android level

As shown below: (note the right side of the picture)

img

Binder principle.png

The mutual communication between Client/Server/ServiceManager in the figure is based on the Binder mechanism. In the figure, the interaction between Clinet/Server/ServiceManager is represented by a dotted line, because they do not directly interact with each other, but all interact through the Binder driver, thereby realizing the IPC communication method. Among them, the Binder driver is located in the kernel space, and the Client/Server/ServiceManager can be regarded as the infrastructure of the Android platform. The Client and Server are the application layers of Android. Developers only need to customize the implementation of the client and server, and can directly perform IPC communication with the help of the basic platform architecture of Android.

3. From the perspective of Binder's architecture

As shown below:

img

Binder Architecture.png

same

Binder IPC belongs to the C/S structure, and the Client part is the user code. The user code will eventually call the transact interface of the Binder Driver, and the Binder Driver will call the Server. The Server here is different from the service. It can be understood as the Binder object returned by onBind in the Service. Pay attention to the distinction.

Client side: the code that the user needs to implement, such as the interface class automatically generated by AIDL Binder Driver: the Driver implemented at the kernel layer Server side: this Server is the IBinder object returned by onBind in the Service. It should be noted that the green color blocks above It belongs to the part that the user needs to realize, and the blue part is realized by the system. That is to say, the Binder Driver does not need to know, and a thread pool will be opened in the Server to handle client calls. Why use a thread pool instead of a single-threaded queue? Just imagine, if you use a single-threaded queue, there will be a backlog of tasks, and when multiple clients call a service at the same time, there will be no time to respond, which is absolutely not allowed.

For calling the transact interface in Binder Driver, the client can call it manually or through the proxy class generated by AIDL. The server can inherit the Binder object or the Stub object of the interface class generated by AIDL. These details will be continued below, and will not be expanded here for the time being.

Remember, the implementation of Server here is the way of thread pool, not the way of single-thread queue. The difference is that in the case of single-thread queue, the code of Server is thread-safe, and in the case of thread pool, the code of Server is not thread-safe. Developers do their own multi-thread synchronization.

(3), Binder process

1. Server registers service with SM

img

Register.png

  • 1. First, XXServer (XXX represents a certain one) applies to the Binder driver in its own process to create a Binder entity of XXXService.
  • 2. The Binder driver creates the Binder entity node in the kernel and the Binder reference for this XXXService. Note that the name and the newly created reference are packaged and passed to the SM (the entity is not passed to the SM), and the SM is notified to register a Service named XXX .
  • 3. After SM receives the data packet, it takes out the name and reference of XXXService from it, and fills it into a lookup table
  • 4. At this point, if a Client sends a request to SM to apply for XXXService, then SM can look up the Binder reference of the Service in the table, and return the Binder reference (XXXBpBinder to Client)

Before we learn more about the Binder communication mechanism, let's clarify a few concepts.

  • references and entities. Here, for an entity used for communication (which can be understood as an Object in the real space), there can be multiple references to the entity (without real space, it can be understood as a link of the entity, and the operation reference can operate on the corresponding link entity). If a process holds a certain entity and other processes also want to manipulate the entity, the most efficient way is to obtain a reference to the entity and then manipulate the reference.
  • Some resources also refer to entities as local objects, and applications as remote objects. So it can be understood as follows: the application is sent from the local process to other process operation entities, so it has the names of local and remote objects.

For your better understanding later, here are a few additional concepts

  • Binder entity pair : the Binder entity object is the Binder entity object and the Binder service provider. A class that provides Binder services must inherit the BBinder class. Therefore, sometimes "BBinder object" is used instead of "Binder entity object" in order to emphasize the object type.
  • Binder reference object : The Binder reference object is the representative of the Binder entity object in the client process. The type of each reference object is the BpBiner class, and the name "BpBinder object" can also be used instead of "Binder reference object".
  • Binder proxy object : The proxy object is also an interface object, which mainly provides interface services for the upper-layer application of the client, and is derived from the IInterface class. It implements the function interface of the Binder service, of course it is just an empty shell of a transfer. Through the proxy object, the application can use the remote entity object to provide services like using the local object.
  • IBiner object : The BBinder and BpBinder classes are inherited from the IBinder class. In many occasions, there is no need to deliberately distinguish between entity objects and reference objects. At this time, you can also use "IBinder objects" to call them uniformly.
  • The Binder proxy object mainly deals with applications. The advantage of separating the Binder proxy object from the Binder reference (BpBinder object) is that the proxy object can have many instances, but they contain the same reference object, which facilitates the use of the application layer. . As shown below:

img

Binder object relationship diagram.png

In this way, the application layer can directly discard the interface object and directly use the reference object of Binder, but the compatibility of the program developed in this way is not good. It is also because the client separates the reference object and the proxy object that Android can use a set of architecture to provide Binder services for both the Java and native layers. After isolation, the bottom layer of Binder does not need to relate to the implementation details of the upper layer, but only needs to interact with Binder entity objects and reference objects.

PS: BpBinder (Binder reference object, on the client side) and BBinder (Binder entity, on the server side) are representatives related to Binder communication in Android, and they are derived from the IBiner class (BpBinder and BBinder are in the Native layer, Not in the framework layer), the relationship diagram is as follows:

img

image.png

Client side: BpBinder sends transaction requests by calling transact() Server side: BBinder will receive corresponding transactions through onTransact()

At this time, look at this picture again, and then everyone thinks about it, and you will understand many things.

img

Binder principle.png

2. How to obtain a remote interface of SM

img

get.png

If you're careful enough, you'll see that there's a problem here:

Both SM and Server are processes. Server registers Binder with SM and requires inter-process communication. Currently, inter-process communication is implemented, but inter-process communication is used. It's a bit dizzy, isn't it, it's like the question of which came first, the chicken or the egg.

In fact, Binder solves this problem like this:

  • For the communication mechanism of Binder, the Server side has the Binder entity (BBinder); the Client has the Binder reference (BpBinder).
  • If you regard SM as the server side, let it have its own entity (BBinder) when the Binder driver runs together (the value of the handle of the ServiceManager's Binder is set to 0 in the code). This Binder entity has no name and does not need to be registered. All Clients believe that the binder reference (BpBinder) with a handle value of 0 is used to communicate with the SM. Then this problem is solved.
  • But here comes the problem again, the value of handle in Client and Server is 0 (the reference with value of 0 is specially used for communication with SM), it is not enough, and the entity (BBinder) whose handle value of SM is 0 needs to be 0. You're done. How to achieve it? When a process calls the Binder driver, use ** "BINDER_SET_CONTEXXT_MGR" ** name (in binder_ioctl) to register itself as SM, the Binder driver will automatically create a Binder entity for her. The reference of this Binder is 0 for all Clients.
3. Client obtains the remote interface of Service from SM

After the Server registers the Binder entity and its name with the SM, the Client can obtain the Binder reference (BpBinder) in the SM lookup table using the Service name. The client also uses the reserved reference with a handle value of 0 to request access to a Service from the SM: when applying for a reference to access XXXService. SM will obtain the name of XXXService from the request packet, find the entry corresponding to the name in the lookup table, take out the Binder reference and package it to reply to the Client. Then, the Client can use the XXXService reference to use the XXXService service. If more Clients request the Service, more Clients in the system will get this reference.

As shown below

img

Get Remote Interface.png

4. After the C/S connection is established

First thing to understand:

Client must have its own Binder entity and the application of Server's Binder; Server has its own Binder entity and Client's Binder reference.

We can also analyze according to the way of network requests:

  • Send data from Client to Server: Client is the sender and has Binder entity; Server is the receiver and has Binder reference.
  • Send data from Server to Client: Server is the sender and has Binder entity: Client is the receiver and has Binder reference.

In fact, after we establish the C/S connection, there is no need to consider who is the Client and who is the Server. As long as you clarify who is the sender and who is the receiver, you can know where the Binder entity and application are.

Then let's take a look at the specific process after the C/S connection is established, as shown in the figure below:

img

Process after establishing C/S connection.png

Then let's talk about the specific process:

  • In the first step, the sender requests the sending operation through the Binder entity
  • In the second step, the Binder driver will process this operation request, put the sender's data into the write buffer (binder_write_read.write_buffer) (for the receiver, it is a read buffer), and set read_size (the receiver's read data) as data size.
  • In the third step, the receiver has been in the blocking state before, when the write cache has data, it will read the data and execute the command operation
  • The fourth step, after the receiver finishes executing, it will also encapsulate the returned result with the binder_transaction_data structure and write it into the buffer (for the sender, it is a read buffer)

(4) Anonymous Binder

In Android, Binder can also establish a point-to-point private channel, which is the way of anonymous Binder. In Binder communication, not all communicating Binder entities need to be registered with the SM, and the Server can pass the created Binder entity to the Client through the established entity Binder connection. And this Binder has not registered its name with SM. In this way, the communication between Server and Client has high privacy and security.

As shown below:

img

Anonymous Binder.png

Five, the level of Binder

From the code point of view, the classes designed by Binder can be divided into four levels, as shown in the figure below

img

Binder hierarchy diagram.png

  • The top layer is the various Binder service classes and their interface classes located in Framewok. There are many classes in this layer, such as the common ActivityManagerService (abbreviated as AMS), WindowManagerService (abbreviated as WMS), PackageManagerService (abbreviated as PMS), etc., which provide various services for applications.
  • The middle is divided into two layers, the above is the basis for service class and interface development, such as IBinder, BBinder, BpBinder, etc. The lower layer is the IPCThreadState and ProcessState classes that interact with the driver.
  • The reason for deliberately dividing the classes in the middle libbinder into two levels is that in these four layers, the first layer is closely related to the second layer, and various Binder classes in the second layer are used to support service classes. And the development of proxy classes. However, the coupling between IPCThread on the third layer and the fourth layer is very strong. It is difficult to understand IPCThread or the driver alone. They must be combined to understand. This is where the Binder architecture is criticized. , The driver and the application layer are too coupled, which violates the principles of Linux driver design. Therefore, mainstream Linux is not willing to accept Binder.

Let's take a closer look at Binder

6. Binder protocol

The Biner protocol format is basically "command + data", using the ioctl(fd,cmd,arg) function to achieve interaction. The command is carried by the parameter cmd, and the data is carried by the parameter arg, which does not change depending on the cmd. The following table lists all commands and their corresponding data:

Order meaning parameter (arg)
BINDER_WRITE_READ This command writes or reads data to Binder. The parameters are divided into two sections: the write part and the read part. If write_size is not 0, write the data in write_buffer to Binder; if read_size is not 0, read data from Binder and store it in read_buffer. write_consumered and read_consumered indicate the number of data actually written or read by the Binder driver when the operation is completed struct binder_write_read{ singed long write_size;singed long write_consumed; unsigned long write_buffer; signed long read_size; signed long read_consumed; unsigned long read_buffer; } ;
BINDER_SET_MAX_THREADS This command tells Binder to drive the maximum number of threads in the thread pool of the receiver (usually the Server side). Since the Client sends requests to the Server side concurrently, the Server side must open up a thread pool to provide services for these concurrent requests. Informing the driver of the maximum value of the thread pool is to let the driver find that the number of threads reaches the maximum value of the thread pool. This is to let the driver find that the number of threads reaches this value, so that the receiving end will not be ordered to start the first thread. int max_threads;
BINDER_SET_CONTEXT_MGR The current process is registered as SM. There can only be one SM in the system, as long as the current SM does not call close() to close, the Binder driver cannot have other processes become SM none
BINDER_TREAD_EXIT Notify the Binder driver that the current thread has exited. Binder will establish corresponding data structures for all participating communication threads (including threads in the Server thread pool and threads of requests sent by the Client). These threads must notify the driver to free the corresponding data structures when they exit none
BINDER_VERSION Get the version number of the Binder driver none

The most commonly used command among these is BINDER_WRITE_READ. The parameters of this command consist of two parts:

  • 1. Write data to Binder
  • 2. Read data to Binder

The driver processes the write portion first and then the read portion. The advantage of this arrangement is that the application can flexibly handle commands synchronously or asynchronously. For example, if you want to send an asynchronous command, you can only fill in the write part and set read_size to 0. If you only want to get the data from Binder, you can set the write part to 0, that is, set write_size to 0. If you want to send a request and wait for the return data synchronously, you can put both parts on.

(1), BINDER_WRITE_READ write operation

The format of the data written by Binder is also (command + data). At this time, the commands and data are stored in the memory space pointed to by the write_buffer field in the binder_write_read structure, and multiple commands can be stored continuously. The data is stored immediately after the command, and the format varies according to the command. The following table lists the commands supported by Binder's write operation: I provide two sets, one is pictures, which is convenient for mobile phone users, and the other is text, which is convenient for PC users

img

write operation.png

image above, text below

Order meaning parameter (arg)
BC_TRANSACTION BC_REPLY BC_TRANSACTION is used by Client to send request data to Server; BC_REPLY is used by Server to send reply (response) data to Client. It is followed by a binder_transaction_data structure indicating the data to be written. struct binder_transaction_data
BC_ACQUIRE_RESULT not yet implemented
BC_FREE_BUFFER Free a block of mapped memory. The Binder receiver maps a large memory space through mmap(), and the Binder driver uses the best matching algorithm based on this memory to realize the dynamic allocation and release of the received data cache to meet the requirements of concurrent requests for the receive cache. After the application has processed the data, it must release the buffer as soon as possible with the change command, otherwise it will not be able to accept new data due to the exhaustion of the buffer A pointer to the buffer that needs to be released; the pointer is located in the received Binder packet
BC_INCREFS BC_ACQUIRE BC_RELEASE BC_DECREFS This set of commands increases or decreases the reference count of Binder to implement the function of strong pointer or weak pointer 32-bit Binder reference number
BC_REGISTER_LOOPER BC_ENTER_LOOPER BC_EXIT_LOOPER Together with BINDER_SET_MAX_THREADS, this group of commands implements the Binder driver's management of the receiver's thread pool. BC_REGISTER_LOOPER notifies the driver that a thread in the thread pool has been created; BC_ENTER_LOOPER notifies the driver that the thread has entered the main loop and can accept data; BC_EXIT_LOOPER notifies the driver that the thread exits the main loop and is no longer accepting data. -----
BC_REQUEST_DEATH_NOTIFICATION The process that obtains the Binder reference requires the driver to be notified when the Binder entity is destroyed through this command. Although a strong pointer can ensure that the entity will not be destroyed as long as there is a reference, it is a cross-process reference after all. No one can guarantee that the entity will disappear because the server where it is located shuts down the Binder driver or exits abnormally. give notice now uint32 *ptr; Binder reference that needs to be notified of death void **cookie: Information related to the death notification, the driver will return to the requesting process when the death notification is issued.
BC_DEAD_BINDER Processes that have received notifications of an entity's death use this command to notify the driver after deleting the reference void * cookie

在这些命令中,最常用的h是BC_TRANSACTION/BC_REPLY命令对,Binder请求和应答数据就是通过这对命令发送给接受方。这对命令所承载的数据包由结构体struct binder_transaction_data定义。Binder交互有同步和异步之分。利用binder_transcation_data中的flag区域划分。如果flag区域的TF_ONE_WAY位为1,则为异步交互,即client发送完请求交互即结束,Server端不再返回BC_REPLY数据包;否则Server会返回BC_REPLY数据包,Client端必须等待接受完数据包后才能完成一次交互。

(二)、BINDER_WRITE_READ:从Binder读出数据

在Binder里读出数据格式和向Binder中写入数据格式一样,采用(消息ID+数据)形式,并且多条消息可以连续存放。下面列举从Binder读出命令及相应的参数。 为了照顾手机端的朋友,先发图片

img

Binder读出数据.png

Binder读操作消息ID

消息 含义 参数(arg)
BR_ERROR 发生内部错误(如内存分配失败) ----
BR_OK BR_NOOP 操作完成 ----
BR_SPAWN_LOOPER 该消息用于接受方线程池管理。当驱动发现接收方所有线程都处于忙碌状态且线程池中的线程总数没有超过BINDER_SET_MAX_THREADS设置的最大线程时,向接收方发送该命令要求创建更多的线程以备接受数据。 -----
BR_TRANSCATION BR_REPLY 这两条消息分别对应发送方的 BC_TRANSACTION 和BC_REPLY,表示当前接受的数据是请求还是回复 binder_transaction_data
BR_ACQUIRE_RESULT BR_ATTEMPT_ACQUIRE BR_FINISHED 尚未实现 -----
BR_DEAD_REPLY 交互过程中如果发现对方进程或线程已经死亡则返回该消息 -----
BR_TRANSACTION_COMPLETE 发送方通过BC_TRRANSACTION或BC_REPLY发送完一个数据包后,都能收到该消息作为成功发送的反馈。这和BR_REPLY不一样,是驱动告知发送方已经发送成功,而不是Server端返回数据。所以不管同步还是异步交互接收方都能获得本消息。 -----
BR_INCREFS BR_ACQUIRE BR_RFLEASE BR_DECREFS 这组消息用于管理强/弱指针的引用计数。只有提供Binder实体的进程才能收到这组消息 void *ptr : Binder实体在用户空间中的指针 void **cookie:与该实体相关的附加数据
BR_DEAD_BINDER BR_CLEAR_DEATH_NOTIFICATION_DONE 向获得Binder引用的进程发送Binder实体死亡通知书:收到死亡通知书的进程接下来会返回 BC_DEAD_BINDER_DONE 确认 void *cookie 在使用BC_REQUEST_DEATH_NOTIFICATION注册死亡通知时的附加参数
BR_FAILED_REPLY 如果发送非法引用号则返回该消息 -----

和写数据一样,其中最重要的消息是BR_TRANSACTION或BR_REPLY,表明收到一个格式为binder_transaction_data的请求数据包(BR_TRANSACTION或返回数据包(BR_REPLY))

(三)、struct binder_transaction_data :收发数据包结构

该结构是Binder接收/发送数据包的标准格式,每个成员定义如下: 下图是Binder

img

Binder数据包.png

成员 含义
union{ size_t handle; void *ptr;} target; 对于发送数据包的一方,该成员指明发送目的地。由于目的地是远端,所以在这里填入的是对Binder实体的引用,存放在target.handle中。如前述,Binder的引用在代码中也叫句柄(handle)。 当数据包到达接收方时,驱动已将该成员修改成Binder实体,即指向 Binder对象内存的指针,使用target.ptr来获取。该指针是接受方在将Binder实体传输给其他进程时提交给驱动的,驱动程序能够自动将发送方填入的引用转换成接收方的Binder对象的指针,故接收方可以直接将其当对象指针来使用(通常是将其reinpterpret_cast相应类)
void *cookie; 发送方忽略该成员;接收方收到数据包时,该成员存放的是创建Binder实体时由该接收方自定义的任意数值,做为与Binder指针相关的额外信息存放在驱动中。驱动基本上不关心该成员
unsigned int code ; 该成员存放收发双方约定的命令码,驱动完全不关心该成员的内容。通常是Server端的定义的公共接口函数的编号
unsigned int code; 与交互相关的标志位,其中最重要的是TF_ONE_WAY位。如果该位置上表明这次交互是异步的,Server端不会返回任何数据。驱动利用该位决定是否构建与返回有关的数据结构。另外一位TF_ACCEPT_FDS是处于安全考虑,如果发起请求的一方不希望在收到回复中接收文件的Binder可以将位置上。因为收到一个文件形式的Binder会自动为接收方打开一个文件,使用该位可以防止打开文件过多
pid_t send_pid uid_t sender_euid 该成员存放发送方的进程ID和用户ID,由驱动负责填入,接收方可以读取该成员获取发送方的身份。
size_t data_size 驱动一般情况下不关心data.buffer里存放了什么数据。但如果有Binder在其中传输则需要将其对应data.buffer的偏移位置指出来让驱动知道。有可能存在多个Binder同时在数据中传递,所以须用数组表示所有偏移位置。本成员表示该数组的大小。
union{ struct{ const void *buffer; const void * offset; } ptr; uint8_t buf[8];} data; data.buffer存放要发送或接收到的数据;data.offsets指向Binder偏移位置数组,该数组可以位于data.buffer中,也可以在另外的内存空间中,并无限制。buf[8]是为了无论保证32位还是64位平台,成员data的大小都是8字节。

PS:这里有必要强调一下offsets_size和data.offsets两个成员,这是Binder通信有别于其他IPC的地方。就像前面说说的,Binder采用面向对象的设计思想,一个Binder实体可以发送给其他进程从而建立许多跨进程的引用;另外这些引用也可以在进程之间传递,就像java将一个引用赋值给另外一个引用一样。为Binder在不同进程中创建引用必须有驱动参与,由驱动在内核创建并注册相关的数据结构后接收方才能使用该引用。而且这些引用可以是强类型的,需要驱动为其维护引用计数。然后这些跨进程传递的Binder混杂在应用程序发送的数据包里,数据格式由用户定义,如果不把他们一一标记出来告知驱动,驱动将无法从数据中将他们提取出来。于是就是使用数组data.offsets存放用户数据中每个Binder相对于data.buffer的偏移量,用offersets_size表示这个数组的大小。驱动在发送数据包时会根据data.offsets和offset_size将散落于data.buffer中的Binder找出来并一一为它们创建相关的数据结构。

七、Binder的整体架构

img

Binder的整体架构.png

文末

For more Android framework-related information, you can scan the QR code below to get it!

## **Android 11.0 Latest Framework Analysis》**

Table of contents

img

img

Chapter 1 System Startup

​ ● Section 1 Android System Structure

​ ● Section 2 How does Android start

​ ● Section 3 Android 11.0 system startup init process

​ ● Section 4 Zygote process started by Android 11.0 system

​ ● Section 5 SystemServer process started by Android 11.0 system

​ ● Section 6 ActivityMnagerService-AMS startup process of Android 11.0 system service

​ ● Section 7 Launcher (desktop) startup process of Android 11.0 system startup

​ ● Section 8 Android11.0 application process creation process and Zygote fork process

​ ● Section 9 Android 11.0 PackageManagerService (1) Working principle and startup process

​ ● Section 10 Android 11.0 PackageManagerService-APK installation process

img

Chapter 2 Log System

​ ● The first section Android11.0 log system analysis - logd, logcat instruction description, classification and attributes

img

Chapter 3 Binder Communication Principle

​ ● Section 1 Android11.0 Binder Communication Principles (1) Summary of Binder, HwBinder, VndBinder

​ ● Section 2 Android 11.0 Binder Communication Principles (2) - Getting Started with Binder

​ ● Section 3 Android 11.0 Binder Communication Principles (3) - ServiceManager

​ ● Section 4 Android11.0 Binder Communication Principle (4) - Native-C\C++ Example Analysis

​ ● Section 5 Android 11.0 Binder Communication Principle (5) - Binder Driver Analysis

​ ● Section 6 Android 11.0 Binder Communication Principles (6) - How Binder Data Completes Targeted Attacks

​ ● Section 7 Android11.0 Binder Communication Principle (7) - Framework binder example

​ ● Section 8 Android11.0 Binder Communication Principle (8) - Framework Layer Analysis

​ ● Section 9 Android11.0 Binder Communication Principle (9) - AIDL Binder Example

​ ● Section 10 Android11.0 Binder Communication Principles (10) - AIDL Principle Analysis - Proxy-Stub Design Pattern

​ ● Section 11 Android11.0 Binder Communication Principles (11) - Binder Summary

img

Chapter 4 HwBinder Communication Principles

​ ● Section 1 Introduction to HwBinder - Android 10.0 HwBinder Communication Principles (1)

​ ● Section 2 HIDL Detailed Explanation - Android10.0 HwBinder Communication Principle (2)

​ ● Section 3 HIDL Example-C++ Service Creation Client Verification-Android10.0 HwBinder Communication Principle (3)

​ ● Section 4 HIDL Example-JAVA Service Creation-Client Verification-Android10.0 HwBinder Communication Principle (4)

​ ● Section 5 HwServiceManager - Android 10.0 HwBinder Communication Principles (5)

​ ● Section 6 Registration Principle of Native Layer HIDL Service - Android 10.0 HwBinder Communication Principle (6)

​ ● Section 7 Registration Principle of JAVA Layer HIDL Service - Android10.0 HwBinder Communication Principle

​ ● Section 8 HwBinder Driver - Android 10.0 HwBinder Communication Principle

​ ● Section 9 Summary of HwBinder Principles - Android 10.0 HwBinder Communication Principles

Guess you like

Origin blog.csdn.net/Gaga246/article/details/131246512