http://blog.youkuaiyun.com/yangwen123/article/details/9100599
版权声明:本文为博主原创文章,未经博主允许不得转载。
Binder通信进程描述——binder_proc
进程打开设备文件/dev/binder之后,还必须调用函数mmap将它映射到进程的地址空间来,实际上是请求Binder驱动程序为它分配一看内核缓冲区,以便用来接收进程间通信数据。Binder驱动程序为进程分配的内核缓冲区的大小保存在成员变量buffer_size中。这些内核缓冲区有内核空间地址和用户空间地址两个地址,内核空间地址保存在成员变量buffer中,用户空间地址保存在成员变量vma中,用户空间程序通过用户空间地址来访问内核缓冲区,内核缓冲区的内核空间地址和用户空间地址之间相差一个固定值,保存在成员变量user_buffer_offset中。这样就可以通过一个用户空间地址或内核空间地址来计算出另外一个地址的大小。这两个地址都是虚拟地址,对应的物理页面保存在成员变量pages中,Binder驱动程序开始时只为内核缓冲区分配一个物理页面。Binder驱动为了方便管理内核缓冲区,会将它划分成若干小块,使用binder_buffer来描述这些内核缓冲区,并且按地址从小到大保存在成员变量buffers指向的链表中。当使用这些内核缓冲区时就会为其分配物理页面,正在使用的内核缓冲区保存在allocated_buffers红黑树中,而空闲的内核缓冲区保存在free_buffers红黑树中。成员变量保存了空闲内核缓冲区的大小。每个使用了Binder通信机制的进程都有一个Binder线程池,用来处理进程间通信请求,这个Binder线程池由Binder驱动程序来维护,Binder线程池中的线程保存在threads红黑树上。进程可以使用ioctl函数将一个线程注册到Binder驱动程序中,当进程没有足够多的空闲线程来处理进程间通信请求时,Binder驱动程序可以主动要求进程注册更多的线程到Binder线程池中。Binder驱动程序最多可以主动请求进程注册的线程的数量保存在成员变量max_threads中,并不表示Binder线程池中的最大线程数目,成员变量ready_threads表示进程当前空闲Binder线程数目。Binder驱动程序每一次主动请求进程注册一个线程时,都会将成员变量requested_threads的值加1,当进程响应这个请求之后,Binder驱动程序就会将成员变量requested_threads的值减1,同时将requested_threads_started的值加1,表示驱动程序已经主动请求进程注册了多少个线程到Binder线程池中。当进程接收到一个进程间通信请求时,Binder驱动程序就将该请求封装成一个工作项,并且加入到进程的待处理队列todo中,Binder线程池中的空闲Binder线程会睡眠在wait所描述的一个等待队列中,当它们的宿主进程的待处理工作项队列增加了新的工作项之后,Binder驱动程序会唤醒这些线程去处理新的工作项,同时线程优先级被设置为default_priority值。一个进程包含一系列的Binder实体对象和Binder引用对象,这些Binder实体对象binder_node的成员变量ptr保存在成员变量nodes红黑树中,所有Binder引用对象的成员变量desc组织在refs_by_desc红黑树中,所有Binder引用对象的成员变量node组织在refs_by_node红黑树中。Binder线程池中空闲Binder线程睡眠在一个等待队列中,进程可以通过调用flush函数来唤醒这些线程,以便它们可以检查进程是否有新的工作项需要处理。
Binder线程描述——binder_thread
Binder实体对象——binder_node
binder_node用来描述一个Binder实体对象,每个Service组件在Binder驱动程序中都对应有一个Binder实体对象,用来描述它在内核中的状态。Android系统的Binder通信框架如下图所示:用户空间中的每一个Binder本地对象在Binder驱动中都对应有一个Binder实体对象,成员变量proc指向Binder实体对象的宿主进程,宿主进程使用红黑树来维护它内部的所有Binder实体对象,成员变量rb_node就是用来挂载到宿主进程proc的Binder实体对象红黑树中的节点;如果该Binder实体对象的宿主进程已经死亡,该Binder实体就通过成员变量dead_node保存到全局链表binder_dead_nodes。一个Binder实体对象可以被多个client引用,成员变量refs用来保存所有引用该Binder实体的Binder引用对象,internal_strong_refs和local_strong_refs都是用来描述Binder实体对象的强引用计数,而local_weak_refs则是用来描述Binder实体对象的弱引用计数。成员变量ptr和cookie分别指向用户空间地址,cookie指向BBinder的地址,ptr指向BBinder对象的引用计数地址。has_async_transaction用来描述一个Binder实体对象是否正在处理一个异步事务,当Binder驱动指定某个线程来处理某一事务时,首先将该事务保存到指定线程的todo队列中,表示要由该线程来处理该事务。如果是异步事务,Binder驱动程序就会将它保存在目标Binder实体对象的一个异步事务队列async_todo队列中。min_priority表示一个Binder实体对象在处理来自client进程请求时所要求处理线程的最小线程优先级。
Binder引用对象——binder_ref
binder_ref用来描述一个Binder引用对象,每一个client在Binder驱动中都有一个binder引用对象。成员变量node保存该binder引用对象所引用的Binder实体对象,Binder实体对象使用链表保存了所有引用该实体对象的Binder引用对象,node_entry就是该Binder引用对象所引用的Binder实体对象的成员变量refs链表中的节点,desc是一个句柄值,用来描述一个Binder引用对象。当Client进程通过句柄值来访问某个Service服务时,Binder驱动程序可以通过该句柄值找到对应的Binder引用对象,然后根据该Binder引用对象的成员变量node找到对应的Binder实体对象,最后通过该Binder实体对象找到要访问的Service。proc执行该Binder引用对象的宿主进程,rb_node_desc和rb_node_node是binder_proc中红黑树refs_by_desc和refs_by_node的节点。
内核缓存区描述符——binder_buffer
binder_buffer用来描述一个内核缓冲区,用来在进程间传输数据。每个使用Binder进程通信机制的进程在Binder驱动中都有一个内核缓冲区列表,用来保存Binder驱动程序为它分配的内核缓冲区,成员变量entry就是这个内核缓冲区列表中的节点,binder_proc使用两个红黑树free_buffers和allocated_buffers来保存正在使用的内核缓冲区和空闲内核缓冲区,rb_node就是这两棵红黑树的节点。成员变量transaction和target_node用来描述一个内核缓冲区正在交给那个事务及那个Binder实体对象使用,data指向一块大小可变的数据缓冲区,真正用来保存通信数据,数据缓冲区保存普通数据和Binder对象,由于数据缓冲区中的普通数据和Binder对象是混合保存在一起的,没有固定顺序,在数据缓冲区后面用一个偏移数组来记录每一个Binder对象在数据缓冲区中的位置,该偏移数组的大小保存在成员变量offsets_size中,而缓冲区的大小保存在成员变量data_size中。
进程通信事务——binder_transaction
binder_transaction用来描述进程间通信过程。need_reply用来区分一个事务是同步还是异步事务,from指向发起事务的线程,to_proc指向负责处理该事务的进程,to_thread指向处理该事务的线程;当Binder驱动为目标进程或线程创建事务时,通过work设置事务类型,然后添加到进程或者线程的todo队列中等待处理;一个线程在处理一个事务时,Binder驱动程序需要修改它的优先级,在修改前,首先将线程的原有优先级保存在saved_priority中,以便线程处理完该事务后可以恢复原来的优先级。成员变量buffer指向Binder驱动程序为该事务分配的一块内核缓冲区,该缓冲区保存了通信数据。
进程通信数据——binder_transaction_data
binder_transaction_data用来描述进程间通信过程中传输的数据,target用来描述目标Binder实体对象或者目标Binder引用对象,如果描述的是目标Binder实体对象,那么成员变量ptr就指向该Binder本地对象BBinder内部的弱引用计数的地址,如果描述的是目标Binder引用对象,那么成员变量handle就指向该Binder引用对象的句柄值。cookie指向Binder本地对象BBinder的地址,成员变量data_size用来描述一个通信数据缓冲区,offset_size用来描述一个偏移数组的大小,data指向一个通信数据缓冲区,当通信数据较小时,就直接使用buf来传输数据,当通信数据较大时,就需要使用一块动态分配的缓冲区来传输数据。ptr指向这块动态缓冲区,buffer指向保存通信数据的数据缓冲区,当数据缓冲区中包含有Binder对象时,offsets就用来保存每一个Binder对象在数据缓冲区的偏移。
-
顶
- 1
-
踩
- 0