Turn http://blog.csdn.net/universus/article/details/6211589
Keywords
Binder Android IPC Linux Kernel Drive
Summary
Binder is one of the inter-process communication (IPC) modes of Android systems. Linux already has pipelines, system V ipc,socket and other IPC tools, but also relies on binder to achieve interprocess communication, which demonstrates the incomparable advantages of binder. An in-depth understanding of binder and comparison with traditional IPC helps us to understand the implementation of interprocess communication and performance optimization. This paper will make a comprehensive elaboration of binder design details, first of all, by introducing binder communication model and Binder communication protocol to understand the design requirements of binder, and then explain the binder in different parts of the system and the role of the expression Finally, the design considerations of binder at the data receiving end are explained, including thread pool management, memory mapping and wait queue management. Through the detailed introduction of binder and the comparison with other IPC communication methods, readers will have an in-depth understanding of the advantages of binder and the reasons for using binder as the main IPC mode of Android.
1 Introduction
The communication method based on Client-server is widely used in various fields, from Internet and database access to embedded handheld device internal communication. In the smartphone platform, especially Android, in order to provide rich and varied functions to the application developers, this communication mode is ubiquitous, such as media playback, video frequency capture, to a variety of mobile phones more intelligent sensors (acceleration, azimuth, temperature, light brightness, etc.) are managed by different servers, Applications can use these services simply as a client to establish a connection with these servers, with little time and effort to develop dazzling functionality. The widespread adoption of the client-server approach is a challenge to interprocess communication (IPC) mechanisms. The current Linux-supported IPC includes traditional pipelines, System V IPC, which is the message queue/shared memory/semaphore, and the socket only supports Client-server communication mode. Of course, you can also set up a protocol on these underlying mechanisms to achieve client-server communication, but this increases the complexity of the system, in the mobile phone this condition is complex, resources scarce environment, the reliability is also difficult to guarantee.
On the other hand, transmission performance. Socket as a general-purpose interface, its low transmission efficiency, high overhead, mainly used in cross-network inter-process communication and the local process of low-speed communication. Message Queuing and pipelines use storage-forwarding, where the data is copied from the sender buffer to the kernel-opened buffer, and then copied from the kernel buffer to the receiver buffer, at least two copies of the process. Shared memory, although not copied, is complex and difficult to use.
Table 1 Number of data copies in various IPC ways
Ipc |
Number of copies of data |
Shared memory |
0 |
Binder |
1 |
socket/Pipeline/Message Queuing |
2 |
Another point is for security reasons. Android as an open-ended, with a large number of developers of the platform, the wide range of applications, to ensure the security of the intelligent terminal is very important. End users do not want to download the program from the Internet without the knowledge of peeping private data, connected to wireless networks, long-term operation of the underlying equipment resulting in a rapid depletion of the battery and so on. Traditional IPC does not have any security measures, relying entirely on the upper layer protocol to ensure. First, the receiver of the traditional IPC is unable to obtain the UID/PID (user ID/Process IDs) of the opposing process, so that the identity of the other party cannot be identified. Android assigns its own UID to each installed application, so the UID of the process is an important sign of identification of the process. Using traditional IPC can only be used by the user to fill in the Uid/pid in the packet, but this is unreliable, easy to be exploited by malicious programs. A reliable identity token is only added by the IPC mechanism itself in the kernel. Second, the traditional IPC access point is open and cannot establish a private channel. For example named pipe name, System V key value, socket IP address or file name is open, as long as they know that the access point of the program can establish a connection to the end, no matter how to prevent the malicious program by guessing the receiver address to obtain the connection.
For these reasons, Android needs to establish a new IPC mechanism to meet the system's requirements for communication, transmission performance and security, which is binder. Binder based on the Client-server communication mode, the transfer process only one copy, for sending the Uid/pid identity, both support real name binder and anonymous binder support, high security.
2 Object-oriented Binder IPC
Binder uses Client-server communication: a process as a server to provide services such as video/audio decoding, video capture, address this query, network connectivity, and so on; Multiple processes initiate service requests to the server as a client to obtain the required services. To achieve client-server communication, the following two points must be achieved: first, the server must have a definite access point or address to accept the client's request, and the client can be in some way to learn the address of the server The second is to develop command-reply protocol to transmit data. For example, in network traffic, the access point of the server is the IP address + port number of the server host, and the transport Protocol is the TCP protocol. For binder, Binder can be seen as the access point that the server provides to implement a particular service, and the client through this ' Address ' sends a request to the server to use the service; For the client, binder can be viewed as a conduit entry to the server, and in order to communicate with a server you must first establish the pipeline and obtain a pipeline entry.
Unlike other IPC, Binder uses object-oriented thinking to describe the binder that accesses the access point and its entry in the client: Binder is an object in the server that provides a set of methods for implementing a request to a service, like a member function of a class. The portal, which is spread over the client, can be viewed as a ' pointer ' to the Binder object, and once the ' pointer ' is obtained, the object's method can be invoked to access the server. In the client's view, it is no different to call the method provided by the binder ' pointer ' and to invoke any other local object through the pointer, although the former entity is in the remote server and the latter entity is in local memory. The ' pointer ' is a C + + term, and more commonly a reference, that is, the client accesses the server through a binder reference. Another term ' handle ' in the field of software can also be used to describe how binder exists in the client. From a communication point of view, the binder in the client can also be seen as the ' proxy ' of the server binder, which serves the client locally on behalf of the remote server. This article uses the term ' reference ' or ' handle ' as the two widely used terms.
The introduction of object-oriented thinking transforms interprocess communication into a method that invokes the object through a reference to a binder object, which is unique in that the Binder object is an object that can be referenced across processes, its entities are in a process, and its references are scattered throughout the system's processes. Most tempting of all, this reference can be as strong or weak as a reference in Java, and can be passed from one process to another, so that everyone can access the same server, just like assigning an object or reference to another reference. Binder blurs the process boundary, fades the process of interprocess communication, and the whole system seems to run in the same object-oriented program. The various binder objects as well as the dotted references are glued to the glue of each application, which is the original intent of binder in English.
Of course object-oriented is only for the application, for Binder drive and kernel other modules using the C language implementation, there is no concept of classes and objects. Binder drivers provide the underlying support for object-oriented interprocess communication.
3 Binder Communication Model
The binder framework defines four roles: Server,client,servicemanager (hereafter referred to as smgr) and binder drivers. Where Server,client,smgr is running in user space and the drive is running in kernel space. The relationship between the four roles is similar to the Internet: Server is the client terminal, Smgr is the domain name server (DNS), and the driver is the router.
3.1 Binder Drive
Like routers, binder drivers, while obscure, are at the heart of communication. Even though the name ' drive ' does not actually have anything to do with the hardware device, it is implemented in the same way as the device driver: It works in the kernel State, provides standard file operations such as open (), mmap (), poll (), IOCTL (), and registers the misc device in the device directory with the character drive device. /dev, the user accesses it through/dev/binder. The driver is responsible for the establishment of binder communication between processes, binder transfer between processes, binder reference count management, packet transfer and interaction between processes, and a series of underlying support. A set of interface protocols is defined between the driver and the application, and the main function is implemented by the IOCTL () interface, which does not provide the read (), write () interface, because the IOCTL () is flexible and can be called once to implement write-before-read to satisfy the synchronous interaction without having to call write () and read ()。 The binder-driven code is located in the drivers/misc/binder.c of the Linux directory.
3.2 ServiceManager and real name Binder
Similar to DNS, Smgr's role is to convert the binder name in the form of a character into a reference to the binder in the client, allowing the client to obtain a reference to the binder entity in the server through the binder name. The binder that registered the name is called the real binder, just as each website has its own URL in addition to an IP address. The server creates a binder entity, takes a character form, reads the easy-to-remember name, sends the binder along with the name as a packet through the binder driver to Smgr, notifies smgr to register a binder called Zhang San, which is located in a server. The driver creates an entity node in the kernel and smgr a reference to the entity in the binder that passes through the process boundary, passing the name and the new reference package to Smgr. After smgr the packet, take the name and the reference from it and fill it in a lookup table.
The attentive reader may find the catch: Smgr is a process, server is another process, and server registers with Smgr Binder will inevitably involve interprocess communication. The current implementation is inter-process communication, but also the use of interprocess communication, it is like eggs can be hatched chicken premise is to find a chicken to hatch eggs. The implementation of Binder is ingenious: Create a chicken in advance to incubate eggs: smgr and other processes also use binder communication, Smgr is the server side, has its own binder object (entity), other processes are client, It is necessary to use this binder reference to implement binder registration, query and fetch. The binder provided by Smgr is special, it has no name and does not need to be registered, and when a process uses the Binder_set_context_mgr command to register itself as a smgr, the binder driver automatically creates binder entities for it (this is the pre-made chicken). Second, the binder's reference is fixed to 0 in all clients without the need for other means. That is, if a server is to register its own binder with smgr, it must communicate through the binder of the 0 reference number and smgr. Analogy network communication, reference No. 0 is like the address of the domain name server, you must be pre-configured manually or dynamically. Note that the client here is relative to Smgr, an application may be a service server, but for smgr it is still a client.
3.3 Client Gets a reference to the real name binder
After the server registers the binder entity and its name with Smgr, the client can obtain a reference to the binder by name. The client also requested access to a binder using the reserved No. 0 reference to Smgr: I applied for a reference to the binder named Zhang San. Smgr receives the connection request, obtains the binder name from the request packet, finds the corresponding entry in the lookup table, extracts the binder reference from the entry, and sends the reference as a reply to the client that initiated the request. From an object-oriented perspective, this Binder object now has two references: one in Smgr and one in the client that originated the request. If there is more client requests for the binder then there will be more references to the binder in the system, just as there are multiple references to an object in Java. and similar references to binders are strongly typed, ensuring that any reference to binder entities is not released. As can be seen through the above process, smgr like a fire ticket to the point, collect all the train tickets, you can buy through it to take the train tickets-get a binder reference.
3.4 Anonymous Binder
Not all binders are required to be registered with Smgr to advertise. The server side can pass the created binder entity to the client through an already established binder connection, although the binder connection that has already been established must be implemented by real name Binder. Since this binder does not register a name with Smgr, it is an anonymous binder. The client will receive a reference to this anonymous binder, which sends a request to an entity located in the server through this reference. Anonymous Binder creates a private channel for both sides of the communication, as long as the server does not send anonymous binders to other processes, the other process cannot obtain a reference to the binder by means of exhaustive or guessing, and sends a request to the binder.
Shows all the roles involved in binder communication, which will be mentioned in a later section.
Figure 1 Binder Communication Example
5 Description of Binder
Examining the whole process of binder communication, it is found that binder exists in the following parts of the system:
· Application processes: In the server process and client processes, respectively
· Binder driver: Manages references to the binder entity and client side of the server, respectively
· Transfer data: Because binder can be passed across processes, it needs to be expressed in the transmitted data
In different parts of the system, binder implements different functions and behaves differently. The next step is to explore the role of binder in each part and the data structure used.
5.1 Binder expression in the application
Although binder uses object-oriented thinking, it does not restrict applications from using object-oriented languages, and it is easy to use binders to communicate in both C and C + + languages. For example, while Android uses java/c++ primarily, processes such as smgr are so important that they are implemented in C language. However, the object-oriented approach is more convenient to describe, so this article assumes that the application is implemented in object-oriented languages.
Binder is essentially a form of underlying communication that is not related to a specific service. To provide a specific service, the server must provide a set of interface functions for the client to use the various services through remote access. The proxy design pattern is usually used: the interface function is defined in an abstract class, and both the server and the client implement all the interface functions for the base class with the abstract class, but the server side is the true function implementation, and the client side is the wrapper for the functions to call the requests remotely. How to combine binder and proxy design patterns is the fundamental problem of application implementation of object-oriented binder communication.
5.1.1 Binder in server-side representations –binder entities
As the basis of the proxy design pattern, we first define an abstract interface class to encapsulate all the functions of the server, which contains a series of pure virtual functions to be implemented by the server and proxy. Since these functions require a cross-process call, they must be numbered one by one, so that the server can decide which function to call based on the number received. The second is to introduce binder. The server side defines another binder abstract class that handles binder request packets from the client, the most important of which is the virtual function ontransact (). The function parses the received packet and invokes the corresponding interface function to process the request.
Next, we use inheritance to construct the binder for the base class of the interface class and Binder abstract class, and implement all the virtual functions in the base class, including the public interface function and the packet processing function: Ontransact (). The input to this function is the packet from the client's binder_transaction_data structure. As mentioned earlier, there is a member code in the structure that contains the interface function number for this request. Ontransact () will parse the code value case-by-case, remove the function parameter from the packet, invoke the corresponding, already implemented public interface function in the interface class. After the function is executed, if you need to return data, build a Binder_transaction_data package to populate it with the return packet.
So when is the ontransact () of each binder entity called? This requires the driver to be involved. As previously stated, binder entities need to be sent to other processes in the form of binde transport structures flat_binder_object to establish binder communication, while binder entity pointers are stored in the handle domain of the structure. The driver obtains the binder's transport structure from the transferred data according to the binder position array, creates a binder node in the kernel for it, and records the binder entity pointer in the node. If there is another process that sends data to the binder, the driver returns the binder entity pointer to the receive thread based on the information recorded in the node binder_transaction_data the target.ptr. The receive thread takes the pointer out of the packet, reinterpret_cast it into a binder abstract class, and calls the Ontransact () function. Since this is a virtual function, different binder entities have their own implementations, which can be called to Ontransact () provided by different binder entities.
5.1.2 Binder in client-side representations –binder references
As part of the proxy design pattern, the client-side binder also inherits the public interface classes provided by the server and implements the public functions. But this is not a real implementation, but a wrapper over a remote function call: Package The function parameters, send the request to the server through binder, and wait for the return value. The binder for this client side also needs to know about binder entities, which are references to binder entities. This reference is either forwarded by Smgr, a reference to a real name binder, or a reference to an anonymous binder sent directly by another process.
Because the same common interface class is inherited, Client Binder provides the same function prototype as the server binder, which makes the user feel that the server is running locally or remotely. In Client Binder, the public interface functions are packaged by creating a binder_transaction_data packet that fills in the code domain with its corresponding encoding. Fill in the Data.buffer point to the cache with the parameters required to invoke the function, and indicate the destination of the packet, that is, a reference to the binder entity that has been obtained, filled in the target.handle of the packet. Note the difference between this and the server: In fact, the target domain is a consortium, including PTR and handle two members, the former used to receive the packet's server, pointing to the binder entity corresponding to the memory space, the latter is used as the requester's client, Holds a reference to the binder entity that tells the driver which entity the packet will be routed to. When the packet is ready, it is sent through the drive interface. The bc_transaction/bc_reply round completes the function's remote call and gets the return value.
Android Bander design and implementation-Design chapter