Android Binder Design and Implementation 5

Source: Internet
Author: User

5.3 Statement of Binder in Driver

Driver is the core of Binder communication. All Binder entities in the system and references of each entity in each process are registered in the driver; the driver must record the many-to-one relationship between the Binder references-> entities; find the corresponding entities for the references; create or find the corresponding references for the entities in a process; record the Binder's locations (in which process); Create/destroy the Binder entity by managing the strong/weak references of the Binder.

When did the Binder in the driver be created? As mentioned above, in order to implement real-name Binder registration, the system must create the first chicken-created for SMgr, and register the Binder entity dedicated to real-name Binder, responsible for inter-process communication during real-name Binder registration. Since the entity has been created, it must also have a reference: The driver reserves the 0 reference in all processes to the Binder entity, that is, the reference 0 of all processes at the beginning indicates that the Binder dedicated to real-name Binder is registered, and any process can register real-name Binder through reference 0 without special operations. Next, as the application continuously registers the real-name Binder, it constantly requests the Binder reference from SMgr, and continuously passes the Binder from one process to another, more and more Binder are traversing the driver in the form of Transmission Structure-flat_binder_object for cross-Process Migration. Because the data. offset array exists in binder_transaction_data, all the Binder that flows through the driver cannot escape the driver's eyes. The Binder will perform the following operations on the Binder that crosses the process boundary: Check the type field of the transmission structure. If it is BINDER_TYPE_BINDER or BINDER_TYPE_WEAK_BINDER, the Binder entity will be created; if BINDER_TYPE_HANDLE or BINDER_TYPE_WEAK_HANDLE is used, the reference of the Binder is created. If BINDER_TYPE_HANDLE is used, the file is opened for the process and no data structure is required. For detailed procedures, see table 7. As more and more Binder entities or references pass through the driver in the process, the driver will create more and more nodes or references in the kernel. Of course, this process is transparent to users.

5.3.1 statement of the Binder entity in the driver

The Binder object in the driver is also called a 'node'. It belongs to the process that provides the entity, represented by the struct binder_node structure:

Table 8 Binder node description structure: binder_node

Member Description
Int debug_id; For debugging
Struct binder_work work; When the reference count of this node changes, you need to notify the process to which it belongs, and then use this member to mount the to-do queue of the process to wake up the process to execute the modification of the Binder object reference count.
Union {
Struct rb_node;
Struct hlist_node dead_node;
};
Each process maintains a red/black tree, and stores all the Binder entities of the process using the pointer of the Binder object in the user space, that is, the ptr Member of the structure as the index. In this way, the driver can quickly find the node in the kernel based on the pointer of the Binder object in the user space. Rb_node is used to link the current node to the red/black tree.
When destroying a node, you must remove the rb_node from the red/black tree. However, if the node still has references that are not cut off, use dead_node to isolate the node from another linked list, the node may not be destroyed until all processes are notified to be disconnected from the reference of the node.
Struct binder_proc * proc; This member points to the process to which the node belongs, that is, the process that provides the node.
Struct hlist_head refs; This member is the queue header, and all references pointing to this node are linked to this queue. These references may belong to different processes. This queue can be used to traverse all references pointing to this node.
Int internal_strong_refs; To implement a counter with a strong pointer: generate a strong reference pointing to the current node and Add 1 to the counter.
Int local_weak_refs; The weak reference count set by the driver for the Binder in the transmission. If a Binder is packaged in a data packet and sent from one process to another, the driver increases the reference count for the Binder until the receiving process uses BC_FREE_BUFFER to notify the driver to release the data zone of the data packet.
Int local_strong_refs; The strong reference count set by the driver for the Binder in the transmission. Same as above.
Void _ user * ptr; Pointer to the Binder object of the user space, from the binder member of flat_binder_object
Void _ user * cookie; Additional pointer to the user space, from the cookie member of flat_binder_object
Unsigned has_strong_ref;
Unsigned pending_strong_ref;
Unsigned has_weak_ref;
Unsigned pending_weak_ref
This group of flag is used to control the Interactive Modification reference count of the process where the driver and the Binder entity are located.
Unsigned has_async_transaction; This member indicates that the node has not completed Asynchronous interaction in the to-do queue. The driver saves all data packets sent to the receiving end in the to-do queue opened by the receiving process or thread. For Asynchronous interaction, the driver implements proper traffic control: if there is Asynchronous interaction in the to-do queue to be processed, the Member is set to 1, this will cause the new Asynchronous interaction to be stored in the structure member asynch_todo queue, rather than directly sent to the to-do queue. The purpose is to make way for Synchronous interaction and avoid blocking the sending end for a long time.
Unsigned accept_fds Indicates whether the node agrees to accept the file-based Binder, from the FLAT_BINDER_FLAG_ACCEPTS_FDS bit of the flags member in flat_binder_object. Because the received file Binder automatically opens a file for the process and occupies a limited file descriptor, the node can set this bit to reject this behavior.
Int min_priority Set the minimum priority of the thread that processes the Binder request. When the sending thread submits data to the receiving thread for processing, the driver also gives the priority of the sending thread to the receiving thread, so that the data can be processed with the same priority even if the process is crossed. However, if the priority of the sending thread is too low, the receiving thread runs at the predefined minimum.
The value of this field is from the flags member in flat_binder_object.
Struct list_head async_todo Asynchronous interaction waiting queue; used to distribute Asynchronous interaction packets sent to the current node
 

Each process has a red/black tree used to store the created nodes, and the Binder pointer in the user space is used as the index. Every time a flat_binder_object representing the Binder entity is detected in the transmitted data, the system first searches for the red and black trees using the binder pointer of the structure as the index. If not found, a new node is created and added to the tree. Because the memory address is unique for the same process, it will not cause confusion due to repeated construction.

5.3.2 description of Binder reference in Driver

Like an object, the Binder reference is created by the Driver Based on flat_binder_object In the transmitted data. It belongs to the process that obtains the reference and is represented by the struct binder_ref struct:

Table 9 Binder reference description structure: binder_ref

Member Description
Int debug_id; Debugging
Struct rb_node rb_node_desc; Each process has a red/black tree. All references of the process are added to the tree by reference signs (that is, the desc domain of the local structure. This member is used as a node to link to the tree.
Struct rb_node rb_node_node; Each process has a red/black tree. All the references of the process are introduced by the memory address of the node entity in the drive (that is, the node domain of the current structure. This member is used as a node to link to the tree.
Struct hlist_node node_entry; This field uses this reference as the refs queue in the Binder object structure binder_node to which the node links
Struct binder_proc * proc; Process to which this reference belongs
Struct binder_node * node; This reference points to the node (Binder entity)
Uint32_t desc; Reference Number of this structure
Int strong; Strong reference count
Int weak; Weak reference count
Struct binder_ref_death * death; The application sends the BC_REQUEST_DEATH_NOTIFICATION or BC_CLEAR_DEATH_NOTIFICATION command to the driver to receive a notification from the driver when the Binder object is destroyed. If this field is not empty, it indicates that the user has subscribed to the 'bad ged' of object destruction '.
 

Just as an object has many pointers, the same Binder object may have many references. The difference is that these references may be distributed in different processes. Like an entity, each process uses a red-black tree to store all references that are being used by the process. However, Binder references can be indexed by two key values:

· The address of the corresponding object in the kernel. Note that this refers to the address of the binder_node structure created by the driver in the kernel, rather than the address of the Binder entity in the user process. The addresses of entities in the kernel are unique, and the use of indexes does not produce ambiguity. However, entities may come from different user processes, and the addresses of entities in different user processes may overlap, it cannot be used for indexing. The driver uses the red/black tree to quickly search for references corresponding to a Binder object in a process (one entity creates only one reference in one process ).

· Reference number. The reference number is a 32-bit identifier allocated by the driver to the reference. It is unique within a process and may have the same value in different processes, this is similar to the process's file opening number. The reference number is returned to the application as a handle referenced by the Binder in the user process. Except that the 0 reference is retained to SMgr in all processes, other values are dynamically allocated by the driver when the reference is created. When a data packet is sent to the Binder, the application fills in the reference number in the target. handle field of the binder_transaction_data structure to indicate the target Binder of the data packet. The driver finds the referenced binder_ref structure in the red/black tree based on the reference number, and then learns the process and other related information of the target Binder entity through its node domain to route data packets.


From LuoXianXiong, your partner

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.