Android Binder 机制初步学习 笔记(一)—— 概述及数据结构介绍
2017-09-25 15:08
615 查看
NOTE
Binder 机制简介
Binder 基础数据结构分析
binderc
1 struct binder_work
2 struct binder_node
3 struct binder_ref_death
4 struct binder_ref
5 struct binder_buffer
6 struct binder_proc
7 struct binder_thread
8 struct binder_transaction
binderh
1 struct binder_write_read
2 enum BinderDriverCommandProtocol
3 enum BInderDriverReturnProtocol
4 struct binder_ptr_cookie
5 struct binder_transaction_data
6 struct flat_binder_object
内核版本:android-goldfish-3.4
内核下载:
Binder 机制简介
Binder 基础数据结构分析
binderc
1 struct binder_work
2 struct binder_node
3 struct binder_ref_death
4 struct binder_ref
5 struct binder_buffer
6 struct binder_proc
7 struct binder_thread
8 struct binder_transaction
binderh
1 struct binder_write_read
2 enum BinderDriverCommandProtocol
3 enum BInderDriverReturnProtocol
4 struct binder_ptr_cookie
5 struct binder_transaction_data
6 struct flat_binder_object
NOTE
源码版本:Android 7.1.2。内核版本:android-goldfish-3.4
内核下载:
git clone https://aosp.tuna.tsinghua.edu.cn/kernel/goldfish.git[/code] (清华镜像站)
以下分析思路均来自老罗的《Android 系统源代码情景分析(修订版)》。Binder 机制简介
Linux 内核提供了多种进程间通讯机制:
Pipe:管道。
Signal:信号。
Message:消息队列。
Share Memory:共享内存。
Socket:插口。
Android 虽是基于 Linux 内核而开发的,但并没有采用这些传统通讯机制,而是自己开发了一套新的机制,即Binder。Binder优势:
进程间传输数据时仅执行一次拷贝操作。
因此提高了效率,同时节省了空间。Binder机制中的关键词:
OpenBinder:Binder机制是在它的基础上实现的。(Wiki:OpenBinder)
CS 通讯方式:客户端Client/ 服务端Server。
Server 进程:提供服务Service的进程。
Client 进程:访问服务的进程。
Service 组件:同一个Server可以运行多个组件向Client提供服务,提供服务的组件即Service组件。
Service 代理对象:同一个Client可以同时向多个Server请求服务,每个请求都对应有一个Client组件,这个组件即是Service代理对象。
Binder 线程池:每个Server与Client进程都会维护一个Binder线程池来处理进程间通讯请求,service的提供与访问是可并发的。
Binder 驱动程序:向用户空间暴露一个设备文件/dev/binder,使应用程序进程可以间接通过它建立通信通道。
Service Manager 组件:Service组件启动,就会将自己注册到一个Service Manager中,以便Client组件可以找到它。
可称为Binder机制的上下文管理者。
可看做一个特殊的Service组件。
open:系统接口,用于打开Binder设备。
mmap:系统接口,提供内存映射操作。
ioctl:系统接口,提供内核缓冲区管理操作,可实现读、写功能。Client、Service、Service Manager与Binder关系:Client、Service与Service Manager运行在用户空间。Binder驱动程序运行在内核空间。
系统提供Service Manager与Binder。Client与Service由应用程序实现。
通过open、mmap、ioctl与Binder设备交互。Binder 基础数据结构分析
NOTE:
结构体中经常能看到成员变量debug_id,它是用来标识Binder实体对象身份,帮助调试Binder驱动的,下面的分析中这个就忽略掉。
数据结构介绍的部分内容比较多,我觉得在这部分,不用一开始就一一理清楚它们的详细用处,只需要大概了解每个结构体的用处就好。等到以后分析实现机制的时候,碰到不太了解的成员变量时再回头来看,这样能理解得比较深刻。1. binder.c
位置:kernel/goldfish/drivers/staging/android/binder.c
该文件中的结构体都是在Binder驱动程序内部进行使用的。1.1 struct binder_work
struct binder_work { struct list_head entry; enum { BINDER_WORK_TRANSACTION = 1, BINDER_WORK_TRANSACTION_COMPLETE, BINDER_WORK_NODE, BINDER_WORK_DEAD_BINDER, BINDER_WORK_DEAD_BINDER_AND_CLEAR, BINDER_WORK_CLEAR_DEATH_NOTIFICATION, } type; };binder_work结构用于描述待处理的工作项。
工作项有可能属于一个进程,也可能属于某个线程。
成员变量:entry:将该结构体嵌入到一个宿主结构中。type:描述工作项类型,可判断出该结构嵌入的宿主类型。1.2 struct binder_node
struct binder_node { int debug_id; struct binder_work work; union { struct rb_node rb_node; struct hlist_node dead_node; }; struct binder_p 4000 roc *proc; struct hlist_head refs; int internal_strong_refs; int local_weak_refs; int local_strong_refs; void __user *ptr; void __user *cookie; unsigned has_strong_ref:1; unsigned pending_strong_ref:1; unsigned has_weak_ref:1; unsigned pending_weak_ref:1; unsigned has_async_transaction:1; unsigned accept_fds:1; unsigned min_priority:8; struct list_head async_todo; };binder_node结构描述一个Binder实体对象。
每个Service组件在驱动中都对应一个Binder实体,描述它在内核中的状态。Binder驱动通过强 (弱)引用计数技术维护实体的生命周期。
成员变量:work:即工作项。proc:指向一个Binder实体对象的宿主进程。rb_node:宿主进程用红黑树维护内部Binder实体,该变量则是红黑树中一个节点。dead_node:宿主进程死亡,这个Binder实体就通过该变量保存在全局hash表中。ref:
一个Binder实体可被多个Client组件引用,于是驱动用binder_ref结构描述这些引用关系。
将引用同一个Binder实体的所有引用保存在hash表中。
该成员变量用于描述这个hash表。
驱动通过它可知哪些Client组件引用了同一Binder实体。internal_strong_refs&&local_strong_refs:描述强引用计数。local_weak_refs:描述弱引用计数。has_strong_ref&&has_weak_ref:
一个Binder实体请求一个Service执行某一操作,则增加该Service组件的强(弱)引用计数。
相应地,Binder实体将它的这两个变量置为1。pending_strong_ref&&pending_weak_ref:
为1时,表明正处于Binder实体向Service组件请求改变引用计数的过程。
为0时,表明上述过程结束。ptr&&cookie:指向用户空间地址。ptr指向Service组件内部引用计数对象(weakref_impl 类型)地址。cookie指向该Service组件地址。has_async_transaction:描述Binder实体是否正在处理异步事务。(1 为是, 0 为否)async_todo:
异步事务队列。
异步事务优先级低于同步,表现为同同一时刻,一个Binder实体所有异步事务至多处理一个,其余等待。而同步事务无限制。min_priority:处理来自Client的请求时,所要求的处理线程(Server中的一个线程)应具备的最小线程优先级。accept_fds:表示是否可接收包含文件描述符的通讯数据(1 可以,0 不可)。1.3 struct binder_ref_death
struct binder_ref_death { struct binder_work work; void __user *cookie; };binder_ref_death用来描述一个Service组件的死亡接收通知:Service组件所在进程可能会意外崩溃。Client进程需要在引用的Service组件死亡时得到通知,以便做出相应处理。
驱动决定向Client发送组件死亡通知时,将该结构体封装成一个工作项,并设置相应work值,再加入到Client的todo队列中等待处理。
成员变量:work:标志一个具体的死亡通知类型。cookie:保存负责接收死亡通知的对象地址。1.4 struct binder_ref
struct binder_ref { /* Lookups needed: */ /* node + proc => ref (transaction) */ /* desc + proc => ref (transaction, inc/dec ref) */ /* node => refs + procs (proc exit) */ int debug_id; struct rb_node rb_node_desc; struct rb_node rb_node_node; struct hlist_node node_entry; struct binder_proc *proc; struct binder_node *node; uint32_t desc; int strong; int weak; struct binder_ref_death *death; };binder_ref结构用来描述一个Binder引用对象:
每个Client组件在Binder驱动中都对应一个引用对象,用于描述它在内核中状态。
驱动通过强(弱)引用计数技术来维护引用对象的生命周期。
成员变量:node:描述引用对象所引用的Binder实体。node_entry:每个Binder实体都有一个hash表,该变量即是这个表的节点。desc:句柄,用于描述Binder引用对象。(其值在进程范围内唯一,所以在不同进程中可能有相同的句柄值存在)proc:指向引用对象的宿主进程。rb_node_desc&&rb_node_node:宿主进程用两个红黑树保存所有Binder引用对象,分别以句柄值和对应Binder实体地址作为关键字,这两个成员变量即为对应的树中节点。strong&&weak:强引用计数与弱引用计数。death:指向一个Service组件的死亡接收通知。1.5 struct binder_buffer
struct binder_buffer { struct list_head entry; /* free and allocated entries by address */ struct rb_node rb_node; /* free entry by size or allocated entry */ /* by address */ unsigned free:1; unsigned allow_user_free:1; unsigned async_transaction:1; unsigned debug_id:29; struct binder_transaction *transaction; struct binder_node *target_node; size_t data_size; size_t offsets_size; uint8_t data[0]; };binder_buffer结构描述一个内核缓冲区,用于进程间数据传输。
成员变量:entry:驱动中内核缓冲区列表的节点。free:表示是否为空闲缓冲区,1为是。rb_node:
进程用两个红黑树保存内核缓冲区信息。free为1,则该变量表示空闲红黑树的节点。free为0,表示正在使用的内存缓冲区红黑树节点。transaction:内核缓冲区正在交给哪个事务。target_node:正在使用缓冲区的Binder实体。allow_user_free:若值为1,当Service组件处理完该事务后,就会请求驱动程序释放该内存缓冲区。async_transaction:表示关联的是否是一个异步事务,是为1,否则为0。data:指向一块大小可变的数据缓冲区,这是通讯数据真正保存的地方。offset_size:偏移数组大小。用于记录Binder对象在缓冲区中位置。data_size:数据缓冲区大小。1.6 struct binder_proc
struct binder_proc { struct hlist_node proc_node; struct rb_root threads; struct rb_root nodes; struct rb_root refs_by_desc; struct rb_root refs_by_node; int pid; struct vm_area_struct *vma; struct mm_struct *vma_vm_mm; struct task_struct *tsk; struct files_struct *files; struct hlist_node deferred_work_node; int deferred_work; void *buffer; ptrdiff_t user_buffer_offset; struct list_head buffers; struct rb_root free_buffers; struct rb_root allocated_buffers; size_t free_async_space; struct page **pages; size_t buffer_size; uint32_t buffer_free; struct list_head todo; wait_queue_head_t wait; struct binder_stats stats; struct list_head delivered_death; int max_threads; int requested_threads; int requested_threads_started; int ready_threads; long default_priority; struct dentry *debugfs_entry; };binder_proc结构描述一个正在使用Binder机制的进程。
成员变量:proc_node:进程调用open打开Binder设备时,驱动会将其映射到binder_proc结构,并保存在全局hash表中,这个变量即是表中的节点。pid:进程的进程组ID。tsk:任务控制块。files:打开文件结构体数组。buffer_size:进程调用mmap将Binder设备映射到进程的地址空间,实际上这是请求驱动为它分配一块内核缓冲区,该成员变量即是缓冲区的大小。buffer:内核空间地址(驱动内部使用)。vma:用户空间地址(应用程序使用)。user_buffer_offset:上面两个地址的差值,用它可以通过一个地址找到另一个地址。buffers:由于buffer指向的是一块大的缓冲区,为方便管理将其分成若干小块,保存在一个列表中,按照地址从小到大顺序排列,而该变量则指向了列表的头部。allocated_buffers:描述一个红黑树,保存了正在使用的(已分配物理页面)的内核缓冲区。free_buffers:红黑树,保存了空闲的内核缓冲区。buffer_free:空闲内核缓冲区的大小。free_async_space:保存当前可用于保存异步事务数据的缓冲区大小。thread:一个红黑树的根节点,以线程ID作为关键字,组织进程的Binder线程池。max_thread:驱动最多可主动请求注册的线程数量。ready_thread:进程当前空闲Binder线程数。todo:待处理工作项队列。wait:等待队列,对应睡眠的空闲BInder线程。default_priority:默认优先级。n 13b53 odes:描述一个红黑树,以Binder实体的成员变量ptr为关键字。refs_by_desc:描述一个红黑树,以Binder引用对象的成员desc为关键字。refs_by_node:描述一个红黑树,以Binder引用对象的成员node为关键字。delivered_death:保存死亡通知工作项的队列。stats:统计进程数据(如接收到的进程间通信请求次数)。deferred_work_node:一个hash表,保存进程可延迟执行的工作项。deferred_work:描述该延迟工作项具体类型。BINDER_DEFERRED_PUT_FILES:与文件描述符关闭相关的延迟。BINDER_DEFERRED_FLUSH:与唤醒空闲Binder线程相关的延迟。BINDER_DEFERRED_RELEASE:与资源释放相关的延迟。enum binder_deferred_state { BINDER_DEFERRED_PUT_FILES = 0x01, BINDER_DEFERRED_FLUSH = 0x02, BINDER_DEFERRED_RELEASE = 0x04, };1.7 struct binder_thread
enum { BINDER_LOOPER_STATE_REGISTERED = 0x01, BINDER_LOOPER_STATE_ENTERED = 0x02, BINDER_LOOPER_STATE_EXITED = 0x04, BINDER_LOOPER_STATE_INVALID = 0x08, BINDER_LOOPER_STATE_WAITING = 0x10, BINDER_LOOPER_STATE_NEED_RETURN = 0x20 }; struct binder_thread { struct binder_proc *proc; struct rb_node rb_node; int pid; int looper; struct binder_transaction *transaction_stack; struct list_head todo; uint32_t return_error; /* Write failed, return error code in read buf */ uint32_t return_error2; /* Write failed, return error code in read */ /* buffer. Used when sending a reply to a dead process that */ /* we are also waiting on */ wait_queue_head_t wait; struct binder_stats stats; };binder_thread结构描述了Binder线程池中的一个线程。
成员变量:proc:指向宿主进程。rb_node:红黑树中的节点(进程用一个红黑树组织线程池中的线程)。pid:线程ID。looper:线程状态。BINDER_LOOPER_STATE_REGISTERED:驱动程序请求注册线程的情况。BINDER_LOOPER_STATE_ENTERED:应用程序主动注册线程的情况。BINDER_LOOPER_STATE_EXITED:线程退出时。BINDER_LOOPER_STATE_INVALID:异常情况。BINDER_LOOPER_STATE_WAITING:空闲状态。BINDER_LOOPER_STATE_NEED_RETURN:表示线程需要马上返回用户空间。todo:保存来自Client的请求(指定该线程处理)的队列。transaction_stack:描述事务的堆栈。wait:线程正在处理事务T1,同时需要其他线程处理另一个事务T2,此时它就会睡眠在wait队列中,直到T2处理完成。return_error&&return_error2:异常情况时返回的错误信息。stats:统计线程数据,如收到的通信请求次数。1.8 struct binder_transaction
struct binder_transaction { int debug_id; struct binder_work work; struct binder_thread *from; struct binder_transaction *from_parent; struct binder_proc *to_proc; struct binder_thread *to_thread; struct binder_transaction *to_parent; unsigned need_reply:1; /* unsigned is_dead:1; */ /* not used at the moment */ struct binder_buffer *buffer; unsigned int code; unsigned int flags; long priority; long saved_priority; uid_t sender_euid; };binder_transaction结构描述了进程间的通信过程:
通常称这个过程为事务。
成员变量:need_reply:区分事务是同步(值为 1)或异步(值为 0)。from:指向发起事务的线程(源线程)。to_proc:指向负责处理该事务的进程(目标进程)。to_thread:指向负责处理该事务的线程(目标线程)。priority:源线程优先级。sender_euid:用户ID。saved_priority:修改线程优先级时的原值存档。buffer:指向驱动为该事务分配的一块内核缓冲区。code&&flag:从进程间通信数据中拷贝而来,具体内容参考结构体binder_transaction_data。from_parent:描述事务所依赖的另一个事务。to_parent:描述目标线程下一个需要处理的事务。2. binder.h
位置:kernel/goldfish/drivers/staging/android/binder.h2.1 struct binder_write_read
#define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read) struct binder_write_read { signed long write_size; /* bytes to write */ signed long write_consumed; /* bytes consumed by driver */ unsigned long write_buffer; signed long read_size; /* bytes to read */ signed long read_consumed; /* bytes consumed by driver */ unsigned long read_buffer; };
宏BINDER_WRITE_READ是最重要的IO控制命令,它控制读写操作。binder_write_read结构描述进程间通信过程中传输的数据。
成员变量:
输入数据:write_buffer:指向一个用户空间缓冲区,内容为要传输到驱动的数据。write_size:相应缓冲区大小。write_consumed:描述驱动从缓冲区中处理了多少字节数据。
输出数据:read_buffer:指向一个用户空间缓冲区,内容为驱动返回到用户空间的结果数据。read_size:缓冲区大小。read_consumed:应用程序从缓冲区中处理的字节数量。write_buffer&&read_buffer的格式:
都是数组,数组每个元素都由一个通信协议代码及其通信数据组成。
命令协议代码:write_buffer中使用的协议代码。
通过BinderDriverCommandProtocol定义。
返回协议代码:read_buffer中使用的协议代码。
通过BinderDriverReturnProtocol定义。
结构图如下。2.2 enum BinderDriverCommandProtocol
enum BinderDriverCommandProtocol { BC_TRANSACTION = _IOW('c', 0, struct binder_transaction_data), BC_REPLY = _IOW('c', 1, struct binder_transaction_data), /* * binder_transaction_data: the sent command. */ BC_ACQUIRE_RESULT = _IOW('c', 2, int), /* * not currently supported * int: 0 if the last BR_ATTEMPT_ACQUIRE was not successful. * Else you have acquired a primary reference on the object. */ BC_FREE_BUFFER = _IOW('c', 3, int), /* * void *: ptr to transaction data received on a read */ BC_INCREFS = _IOW('c', 4, int), BC_ACQUIRE = _IOW('c', 5, int), BC_RELEASE = _IOW('c', 6, int), BC_DECREFS = _IOW('c', 7, int), /* * int: descriptor */ BC_INCREFS_DONE = _IOW('c', 8, struct binder_ptr_cookie), BC_ACQUIRE_DONE = _IOW('c', 9, struct binder_ptr_cookie), /* * void *: ptr to binder * void *: cookie for binder */ BC_ATTEMPT_ACQUIRE = _IOW('c', 10, struct binder_pri_desc), /* * not currently supported * int: priority * int: descriptor */ BC_REGISTER_LOOPER = _IO('c', 11), /* * No parameters. * Register a spawned looper thread with the device. */ BC_ENTER_LOOPER = _IO('c', 12), BC_EXIT_LOOPER = _IO('c', 13), /* * No parameters. * These two commands are sent as an application-level thread * enters and exits the binder loop, respectively. They are * used so the binder can have an accurate count of the number * of looping threads it has available. */ BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct binder_ptr_cookie), /* * void *: ptr to binder * void *: cookie */ BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_ptr_cookie), /* * void *: ptr to binder * void *: cookie */ BC_DEAD_BINDER_DONE = _IOW('c', 16, void *), /* * void *: cookie */ };
命令协议 – 枚举成员:
进程间请求执行操作:BC_TRANSACTION:请求驱动将通信数据传递到目标进程。BC_REPLY:请求驱动将结果传递给源进程。BC_ACQUIRE_RESULT:当前驱动程序实现中不支持。BC_FREE_BUFFER:释放相应的内核缓冲区。
Binder 引用对象计数(根据句柄值获取对象):BC_INCREFS&&BC_DECREFS:增加/减少弱引用计数。BC_ACQUIRE&&BC_RELEASE:增加/减少强引用计数。
驱动第一次增加一个 Binder 实体引用计数:BR_ACQUIRE(返回协议):请求对应Service进程增加相应Service组件强引用计数。BR_INCREFS(返回协议):请求对应Service进程增加相应Service组件弱引用计数。BC_ACQUIRE_DONE&&BC_INCREFS_DONE:返回操作结果给驱动。BC_ATTEMPT_ACQUIRE:当前驱动实现中不支持。
线程注册:BC_REGISTER_LOOPER:线程将自己注册到驱动后,给驱动的通知。BC_ENTER_LOOPER:驱动主动请求进程注册新线程到线程池,线程成功注册后通知。BC_EXIT_LOOPER:线程退出,通知驱动注销线程。
死亡接收通知:BC_REQUEST_DEATH_NOTIFICATION:向驱动注册关于它所引用的Service组件的死亡通知。BC_CLEAR_DEATH_NOTIFICATION:注销之前注册的死亡接收通知。BC_DEAD_BINDER_DONE:进程获得Service组件死亡通知时,告知驱动它已处理。2.3 enum BInderDriverReturnProtocol
enum BinderDriverReturnProtocol { BR_ERROR = _IOR('r', 0, int), /* * int: error code */ BR_OK = _IO('r', 1), /* No parameters! */ BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data), BR_REPLY = _IOR('r', 3, struct binder_transaction_data), /* * binder_transaction_data: the received command. */ BR_ACQUIRE_RESULT = _IOR('r', 4, int), /* * not currently supported * int: 0 if the last bcATTEMPT_ACQUIRE was not successful. * Else the remote object has acquired a primary reference. */ BR_DEAD_REPLY = _IO('r', 5), /* * The target of the last transaction (either a bcTRANSACTION or * a bcATTEMPT_ACQUIRE) is no longer with us. No parameters. */ BR_TRANSACTION_COMPLETE = _IO('r', 6), /* * No parameters... always refers to the last transaction requested * (including replies). Note that this will be sent even for * asynchronous transactions. */ BR_INCREFS = _IOR('r', 7, struct binder_ptr_cookie), BR_ACQUIRE = _IOR('r', 8, struct binder_ptr_cookie), BR_RELEASE = _IOR('r', 9, struct binder_ptr_cookie), BR_DECREFS = _IOR('r', 10, struct binder_ptr_cookie), /* * void *: ptr to binder * void *: cookie for binder */ BR_ATTEMPT_ACQUIRE = _IOR('r', 11, struct binder_pri_ptr_cookie), /* * not currently supported * int: priority * void *: ptr to binder * void *: cookie for binder */ BR_NOOP = _IO('r', 12), /* * No parameters. Do nothing and examine the next command. It exists * primarily so that we can replace it with a BR_SPAWN_LOOPER command. */ BR_SPAWN_LOOPER = _IO('r', 13), /* * No parameters. The driver has determined that a process has no * threads waiting to service incomming transactions. When a process * receives this command, it must spawn a new service thread and * register it via bcENTER_LOOPER. */ BR_FINISHED = _IO('r', 14), /* * not currently supported * stop threadpool thread */ BR_DEAD_BINDER = _IOR('r', 15, void *), /* * void *: cookie */ BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, void *), /* * void *: cookie */ BR_FAILED_REPLY = _IO('r', 17), /* * The the last transaction (either a bcTRANSACTION or * a bcATTEMPT_ACQUIRE) failed (e.g. out of memory). No parameters. */ };
返回协议 – 枚举成员:BR_ERROR:驱动处理应用某个请求时发生异常,则需通知应用进程。BR_OK:驱动成功处理应用请求后,通知应用进程。
Client 进程向 Server 进程发出通信请求:BR_TRANSACTION:驱动通知Server处理请求。BR_REPLY:请求结果数据返回给Client。BR_ACQUIRE_RESULT:当前驱动实现中不支持。BR_DEAD_REPLY:驱动处理通信请求时,若目标死亡,则通知源进程。BR_TRANSACTION_COMPLETE:通知应用,对应的命令协议代码已接收,正在分发给目标进程或目标线程处理。
Service 组件引用计数:BR_INCREFS&&BR_DECREFS:增加/减少弱引用计数。BR_ACQUIRE&&BR_RELEASE:增加/减少强引用计数。BR_ATTEMPT_ACQUIRE:当前驱动实现中不支持。BR_NOOP:通知应用程序执行一个空操作,它的存在是为了方便之后可以替换为BR_SPAWN_LOOPER。BR_SPAWN_LOOPER:驱动发现一个进程没有足够空闲Binder线程处理通信请求时,通知其增加一个新线程到Binder线程池中。BR_FINISHED:当前驱动实现中不支持。
死亡通知:BR_DEAD_BINDER:驱动监测到一个Service组件死亡事件时,通知相应的Client进程。BR_CLEAR_DEATH_NOTIFICATION_DONE:Client通知驱动注销它之前所注册的一个死亡接收通知,驱动执行完注销操作后,通知该Client。BR_FAILED_REPLY:驱动处理一个进程发出的BC_TRANSACTION命令协议时,若发生异常,则通知源进程。2.4 struct binder_ptr_cookie
struct binder_ptr_cookie { void *ptr; void *cookie; };binder_ptr_cookie结构描述一个Binder实体,或描述一个Service组件的死亡接收通知。
成员变量:ptr:
该结构描述Binder实体,则该变量与binder_node结构中ptr等同。
该结构描述Service死亡通知,则指向一个Binder引用对象句柄值。cookie:
该结构描述Binder实体,则该变量与binder_node结构中cookie等同。
该结构描述Service死亡通知,则指向一个用于接收死亡通知的对象的地址。2.5 struct binder_transaction_data
enum transaction_flags { TF_ONE_WAY = 0x01, /* this is a one-way call: async, no return */ TF_ROOT_OBJECT = 0x04, /* contents are the component's root object */ TF_STATUS_CODE = 0x08, /* contents are a 32-bit status code */ TF_ACCEPT_FDS = 0x10, /* allow replies with file descriptors */ }; struct binder_transaction_data { /* The first two are only used for bcTRANSACTION and brTRANSACTION, * identifying the target and contents of the transaction. */ union { size_t handle; /* target descriptor of command transaction */ void *ptr; /* target descriptor of return transaction */ } target; void *cookie; /* target object cookie */ unsigned int code; /* transaction command */ /* General information about the transaction. */ unsigned int flags; pid_t sender_pid; uid_t sender_euid; size_t data_size; /* number of bytes of data */ size_t offsets_size; /* number of bytes of offsets */ /* If this transaction is inline, the data immediately * follows here; otherwise, it ends with a pointer to * the data buffer. */ union { struct { /* transaction data */ const void *buffer; /* offsets from buffer to flat_binder_object structs */ const void *offsets; } ptr; uint8_t buf[8]; } data; };binder_transaction_data描述进程间传输的数据。
成员变量:target:
描述一个目标Binder实体:ptr:指向该实体对应的一个Service组件内部的一个弱引用计数对象(weakref_impl)地址。
描述一个目标Binder引用:handle:指向该引用的句柄值。cookie:由应用程序指定的额外参数。驱动使用BR_TRANSACTION向一个Server发出请求时才有意义,指向的是目标Service组件地址。code:通信的两个进程相互约定好的通信代码。flag:描述进程通信行为特征,取值为enum transaction_flagsTF_ONE_WAY:置1时,表示是异步进程间通信。TF_ROOT_OBJECT:未启用。TF_STATUS_CODE:置1时,表示成员变量data描述的数据缓冲区内容是一个4字节状态码。TF_ACCEPT_FDS:置0时,表示源进程不允许目标进程返回结果中包含文件描述符。
发起通信请求的进程:sender_pid:进程PID。sender_euid:进程UID。data_size&&data_offset:描述通信数据缓冲区大小及偏移量。data:指向一个通信数据缓冲区buf:通信数据较小时用该静态数组传输。ptr:通信数据较大时用该动态分配的缓冲区传输buffer:指向一个数据缓冲区,保存通信数据。offsets:缓冲区中包含Binder对象,则用其描述每个对象的位置。
数据缓冲区中每个Binder对象都使用一个flat_binder_object结构描述,布局结构图如下。2.6 struct flat_binder_object
#define B_PACK_CHARS(c1, c2, c3, c4) \ ((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4)) #define B_TYPE_LARGE 0x85enum { BINDER_TYPE_BINDER = B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE), BINDER_TYPE_WEAK_BINDER = B_PACK_CHARS('w', 'b', '*', B_TYPE_LARGE), BINDER_TYPE_HANDLE = B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE), BINDER_TYPE_WEAK_HANDLE = B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE), BINDER_TYPE_FD = B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE), };/* * This is the flattened representation of a Binder object for transfer * between processes. The 'offsets' supplied as part of a binder transaction * contains offsets into the data where these structures occur. The Binder * driver takes care of re-writing the structure type and data as it moves * between processes. */ struct flat_binder_object { /* 8 bytes for large_flat_header. */ unsigned long type; unsigned long flags; /* 8 bytes of data. */ union { void *binder; /* local object */ signed long handle; /* remote object */ }; /* extra data associated with local object */ void *cookie; };flat_binder_object结构可以描述(根据type区分):
一个Binder实体对象。
一个Binder引用对象。
一个文件描述符。
成员变量:type:取值范围与顶部的宏定义及枚举有关BINDER_TYPE_BINDER:描述强类型Binder实体。BINDER_TYPE_WEAK_BINDER:描述弱类型Binder实体。BINDER_TYPE_HANDLE:描述强类型Binder引用。BINDER_TYPE_WEAK_HANDLE:描述弱类型Binder引用。BINDER_TYPE_FD:描述文件描述符。flag:标志值,当结构描述Binder实体时有意义
第0 ~ 7位:描述Binder实体处理通信请求时,它运行的线程的最小线程优先级。
第8位:描述Binder实体是否可将一块包含文件描述符的数据传输给目标进程。
结构体描述Binder实体:binder:指向实体对应的一个Service组件内部的一个弱引用计数对象的地址。cookie:指向该Service组件地址。
结构体描述Binder引用:handle:描述该引用对象的句柄值。
相关文章推荐
- Android Binder 机制初步学习 笔记(二)—— Binder 设备基本操作实现
- Android Binder 机制初步学习 笔记(三)—— Binder 进程通讯库简介
- Android Binder 机制初步学习 笔记(四,完结)—— Binder 简单应用示例
- Android进程间通信(IPC)机制Binder简要介绍和学习计划
- Android Binder机制学习笔记
- Android进程间通信(IPC)机制Binder简要介绍和学习计划
- Android进程间通信(IPC)机制Binder简要介绍和学习计划
- Android进程间通信(IPC)机制Binder简要介绍和学习计划
- Android进程间通信(IPC)机制Binder简要介绍和学习计划
- Android进程间通信(IPC)机制Binder简要介绍和学习计划
- Android进程间通信(IPC)机制Binder简要介绍和学习计划
- Android进程间通信(IPC)机制Binder简要介绍和学习计划
- Android进程间通信(IPC)机制Binder简要介绍和学习计划
- Android进程间通信(IPC)机制Binder简要介绍和学习计划(转)
- Android进程间通信(IPC)机制Binder简要介绍和学习计划
- Android进程间通信(IPC)机制Binder简要介绍和学习计划
- Android进程间通信(IPC)机制Binder简要介绍和学习计划
- Android进程间通信(IPC)机制Binder简要介绍和学习计划
- Android进程间通信(IPC)机制Binder简要介绍和学习计划
- Android进程间通信(IPC)机制Binder简要介绍和学习计划