<<Android系统源码情景分析>>
说明: 本文主要是参考该书籍,阅读代码.代码环境: Android 8.1 ;Kernel 4.9.
main struct
- binder_work
- binder_node
- binder_ref_death
- binder_ref
- binder_alloc
- binder_buffer
- binder_proc
- binder_thread
- binder_transaction
- binder_driver_command_protocol
- binder_driver_return_protocol
- binder_ptr_cookie
- binder_transaction_data
- flat_binder_object
Service——binder_node(Binder实体对象)
Client——binder_ref(Binder引用对象)
binder_work
// proc, thread, node (async) 分别有独立的 work lists
// 根据 type 类型,将 binder_work 插入到对应的宿主结构中.
struct binder_work { // 描述插入到 worklist 的 work
struct list_head entry; // node enqueued on list
enum {
BINDER_WORK_TRANSACTION = 1,
BINDER_WORK_TRANSACTION_COMPLETE,
BINDER_WORK_RETURN_ERROR,
BINDER_WORK_NODE,
BINDER_WORK_DEAD_BINDER,
BINDER_WORK_DEAD_BINDER_AND_CLEAR,
BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
} type; // 要执行的工作类型
};
binder_node
/**
* 1. binder_node 描述 Binder 实体对象。
* 2. 每一个 Service 组件在 Binder 驱动程序中对应一个 Binder 实体对象,用来描述它在内核中的状态。
* 3. Binder Driver 通过 强引用计数 和 弱引用计数 来维护它们的生命周期。
* 1. proc 指向一个 Binder 实体对象的宿主进程。在 Binder Driver 中,这些宿主进程通过 binder_proc 来描述。
* 2. 宿主进程使用一个红黑树来维护它们内部所有的Binder实体对象,而每一个Binder实体对象的成员变量 rb_node 就正好是红黑树的一个节点。
* 3. 如果 Binder 实体对象的宿主进程死亡了,那么这个Binder实体对象就会通过它的成员变量 dead_node 保存一个全局的 hash 链表中。
*/
// binder_node 对应的是一个 Service 组件,并不对应 一个进程; 因为一个 进程 可以有多个 Service 组件.
struct binder_node {
int debug_id;
spinlock_t lock;
struct binder_work work;
union {
struct rb_node rb_node; // proc 维护的所有的 binder_node 的 红黑树 的节点
struct hlist_node dead_node; // proc 宿主进程已经死亡,那么 binder_node 会保存到全局的 hash list 中
};
struct binder_proc *proc; // proc 指向一个 Binder 实体对象的宿主进程
struct hlist_head refs; // binder_node 描述了 Service 组件,Service 可以被多个 Client 获取,
// refs 维护所有引用了该 Serivce 的 Client 对应的 binder_ref 结构
// 通过该变量就可以知道那些 Client 引用了该 binder_node
int internal_strong_refs; // 引用计数
int local_weak_refs; // 引用计数
int local_strong_refs; // 引用计数
int tmp_refs; // 引用计数
binder_uintptr_t ptr; // 指向 Userspace 的 Service 组件内部的一个引用计数对象(weakref_impl)的地址(用户空间地址)
binder_uintptr_t cookie; // 指向 Userspace 的 Service 组件的地址(用户空间地址)
struct {
/*
* bitfield elements protected by
* proc inner_lock
*/
u8 has_strong_ref:1;
u8 pending_strong_ref:1;
u8 has_weak_ref:1;
u8 pending_weak_ref:1;
};
struct {
/*
* invariant after initialization
*/
u8 sched_policy:2;
u8 inherit_rt:1;
u8 accept_fds:1; // 该 binder_node 是否接收含有 fds 的通信数据
u8 min_priority; // Client 要求的 Server 处理线程的最小优先级
};
bool has_async_transaction; // 该 binder_node 是否正在处理一个 异步事务
struct list_head async_todo; // 该 binder_node 的异步事务 list
/**
* 异步事务的说明:
* 1. 通常情况下,Binder Driver将 一个事务 保存在一个线程的 todo list 中,表示由该线程处理该事务。
* 2. 每一个事务关联一个 binder_node,表示该事务的目标处理对象,即要求该 binder_node 对应的 Service 组件在指定的线程中处理该事务。
* 3. 然而,如果是异步事务,将保存在 binder_node 的 async_todo 中。
*
* 什么是异步事务:
* 单向的,不需要等待应答的进程间通信。
* 异步事务优先级低于同步事务。在同一时刻,一个 binder_node 的所有 异步事务 只有一个会得到处理,其余的都在等待;而同步事务没有该限制。
*/
/**
* 引用技术的说明:
* 1. internal_strong_refs, local_strong_refs 描述 binder_node 的强引用计数。
* 2. local_weak_refs 描述 binder_node 的弱引用计数。
* 3. 一个 binder_node 请求 Service 执行某一操作时,会增加该 Service 的 strong refs 或 weak refs;相应的,binder_node 会将成员变量 has_strong_ref 或 has_weak_ref 的值设置为1.
* 4. 当一个 Service 组件完成一个 binder_node 所请求的操作后,binder_node 就会请求减少该 Service 的 strong refs 或 weak refs。
* 5. binder_node 在请求一个 Service 增加或减少引用计数的过程中,会将成员变量 pending_strong_ref 或 pending_weak_ref 的值设置为1;当 Service 增加或减少了引用计数后,binder_node 就会将这两个成员变量的值设置为0.
* 6. 当 binder_node 的引用计数由0->1, 或由1->0时,Binder Driver 会请求相应的 Service 增加或减少其引用计数。这时候Binder Driver会将修改引用计数的操作封装成一个类型为 binder_node 的工作项,即将 binder_node 的 work 的值设置为 BINDER_WORK_NODE,并将它添加到相应的进程的 todo list 中,等待处理。
*
*/
};
binder_ref_death
struct binder_ref_death {
/**
* @work: worklist element for death notifications
* (protected by inner_lock of the proc that
* this ref belongs to)
*/
struct binder_work work; // 标志死亡类型
binder_uintptr_t cookie; // 属于 Client 的接收死亡通知的 Object address。
};
/**
* 正常情况下,Service 被 Client 引用时,不可以销毁。然而,Client 无法控制 Service 的生命周期,因为 Service 进程可能意外奔溃。
* Client 会在 Service 死亡时,得到通知,以便做出相应的处理。这就需要 Client 将接收死亡通知的对象注册到 Binder Driver 中。
*/
/**
* BINDER_WORK_DEAD_BINDER
* BINDER_WORK_DEAD_BINDER_AND_CLEAR
* BINDER_WORK_CLEAR_DEATH_NOTIFICATION
*
* Binder Driver 在向 Client 发送 死亡通知 时,会将 binder_ref_death 封装成一个工作项,然后添加到 Client 进程的 todo list 中等待处理。
*
* (1) Binder Drvier 探测到 Service 死亡,就会找到 binder_node, 遍历 refs 找到所有的 Client 进程,最后找到 Client 进程注册的 binder_ref_death, Binder Drvier 会将 binder_ref_death 添加到 Client 的 todo list 中等到处理。binder_ref_death 的 work 类型为 BINDER_WORK_DEAD_BINDER。
*
* (2) 当 Client 向 Binder Driver 注册 死亡通知 时,Service 已经死亡,那么Binder Driver会马上发送一个死亡通知给Client。这种情况下,死亡类型为:BINDER_WORK_DEAD_BINDER。
*
* (3) 当 Client 向 Binder Driver 注销一个 死亡通知 时,Binder Driver 也会向该 Client 进程的 todo 队列发送一个 binder_ref_death 的工作项,用来表示注销结果。这时,可能出现两种结果。
* ① 如果Client在注销死亡通知时,Service没有死亡,那么Binder Driver 就会找到 Client 之前注册的 binder_ref_death, 将它封装为 BINDER_WORK_CLEAR_DEATH_NOTIFICATION 的工作项加到 Client 的 todo list 中等待处理。
* ② 如果Client在注销死亡通知时,Service已经死亡,那么 Binder Driver 就会找到 Client 之前注册的 binder_ref_death,将它封装为 BINDER_WORK_DEAD_BINDER_AND_CLEAR 的工作项加到 Client 的 todo list 中等待处理。
*/
binder_ref
binder_ref 描述 Binder 引用对象, 对应于 Client 组件.
struct binder_ref_data {
int debug_id;
uint32_t desc; // binder_ref 的描述句柄。当 Client 访问 Service 时需要指定 desc,根据 desc 找到 binder_ref, 然后找到对应的 Service 组件
int strong; // 强引用计数
int weak; // 弱引用计数
};
struct binder_ref {
/* Lookups needed: */
/* node + proc => ref (transaction) */
/* desc + proc => ref (transaction, inc/dec ref) */
/* node => refs + procs (proc exit) */
struct binder_ref_data data;
struct rb_node rb_node_desc; // binder_proc 的 refs_by_desc 的红黑树的节点。该红黑树以 desc 来组织。
struct rb_node rb_node_node; // binder_proc 的 refs_by_node 的红黑树的节点。该红黑树以 binder_ref 对应的 binder_node 的 地址组织。
struct hlist_node node_entry; // binder_node 使用 node_entry 将所有的 binder_ref 组织为一个 hash list
struct binder_proc *proc; // 指向 binder_ref 的宿主进程
struct binder_node *node; // binder_ref 所引用的 binder_node
struct binder_ref_death *death; // Client 注册的死亡通知描述
};
/**
* 注意:
* binder_ref 的 desc 在一个进程范围内是唯一的,在两个不同的进程中同一个 desc 可能代表两个不同的 Service。
*/
binder_alloc
binder_alloc 是 一个 binder buffer allocator,负责管理所有的 binder_buffer
struct binder_alloc {
struct mutex mutex;
struct task_struct *tsk;
struct vm_area_struct *vma; // vm_area_struct passed to mmap_handler
struct mm_struct *vma_vm_mm; // copy of vma->vm_mm (invarient after mmap)
void *buffer; // base of per-proc address space mapped via mmap
ptrdiff_t user_buffer_offset; // offset between user and kernel VAs for buffer
struct list_head buffers; // 组织所有的 binder_buffer
struct rb_root free_buffers; // 组织所有的 空闲的 binder_buffer
struct rb_root allocated_buffers; // 组织所有的 使用的 binder_buffer
size_t free_async_space; // 可以用来保存异步事务数据的内核缓冲区的大小. 初始化为 mmap 时大小的 1/2
struct page **pages; // 每个 mmap 过的空间对应的 physical page addresses 数组
size_t buffer_size; // mmap 空间大小
uint32_t buffer_free; // 空闲内核缓冲区的大小
int pid;
};
binder_buffer
// 供 binder transactions 使用的 buffer
struct binder_buffer {
struct list_head entry; /* free and allocated entries by address; entry alloc->buffers */
struct rb_node rb_node; /* free entry by size or allocated entry; node for allocated_buffers/free_buffers rb trees */
/* by address */
unsigned free:1;
unsigned allow_user_free:1;
unsigned async_transaction:1; // binder_buffer 所关联的是 异步事务。Binder Driver 会限制异步事务的 buffer 的大小。
unsigned free_in_progress:1;
unsigned debug_id:28;
struct binder_transaction *transaction; // 正在使用该 binder_buffer 的 事务。
struct binder_node *target_node; // binder_buffer 所属的 binder_node
/**
* Binder Driver 使用 binder_transaction 描述一个事务,每个事务关联一个目标 binder_node.
* Binder Drvier 将事务数据保存在 binder_buffer 中,然后将它交给目标 binder_node,目标 binder_node 再将该 binder_buffer 交给 Service 处理。
* Service 处理完该事务后,如果 binder_buffer 的 allow_user_free 为 1, 那么 Service 会请求 Binder Driver 释放 该 binder_buffer。
*/
size_t data_size;
size_t offsets_size;
size_t extra_buffers_size;
void *data;
/**
* data: 保存通信数据
* 1. 若 data 保存的是普通数据,Binder 不需关心,只需要传递给目标对象即可。
* 2. 若 data 保存的是 Binder 对象,Driver 需要维护 Binder 对象对应的 binder_node 或 binder_ref 的生命周期。
* 例如:如果数据缓冲区包含一个 Binder 引用,并且该数据缓冲区是传递给另一个进程的,那么Driver需要为另一个进程创建 binder_ref,并且增加 binder_node 的引用计数。
* 由于 普通数据 和 Binder 对象是混在一起的,他们之间没有固定的顺序,所以需要额外的数据来找到里面的Binder对象。
* 在数据缓冲区的后面,有一个偏移数组,它记录了数据缓冲区中每一个 Binder 对象在数据缓冲区中的位置。偏移数组的大小保存在 offsets_size 中,而数据缓冲区的大小保存在 data_size 中。
*/
};
/**
* binder_buffer 描述一个 内核缓冲区,用来在进程间传递数据。
* 每一个使用 Binder 通信的的进程在 Binder Driver 中都有一个 内核缓冲区链表,用来保存 Binder Driver 为它所分配的内核缓冲区。
*
*/
binder_proc
每一个使用 Binder 通信的 进程 都会用一个 binder_proc 进行描述
struct binder_proc {
struct hlist_node proc_node; // 全局 hash list 的 节点
struct rb_root threads; // 以线程 ID 为关键字组织的进程的 Binder 线程池.
/**
* Binder Process 的 thread pools
* 进程通过 ioctl 将线程注册到 Binder Driver 中,同时,如果没有足够的空闲线程来处理 IPC 请求时,Driver 会请求进程注册更多的线程到 Binder thread pools 中。
*/
struct rb_root nodes; // 组织进程的所有的 binder_node
struct rb_root refs_by_desc; // 根据 binder_ref 的 desc 组织所有的 binder_ref
struct rb_root refs_by_node; // 根据 binder_ref 所引用的 binder_node 的 地址组织所有的 binder_ref
struct list_head waiting_threads; // 组织所有的 wait thread
int pid; // Process ID
struct task_struct *tsk; // 进程的 task_struct
struct hlist_node deferred_work_node; // 组织所有可以延迟执行的工作项
int deferred_work; // 延迟指向的工作项的类型
bool is_dead;
struct list_head todo; // 待处理的 IPC 请求 list
wait_queue_head_t wait;
// 空闲线程会睡眠在 wait 所描述的 等待队列 中,当 宿主进程 的 待处理工作项增加新的工作后,Driver 会唤醒这些线程,以便去处理新的工作项。
struct binder_stats stats; // Binder IPC 通信统计
struct list_head delivered_death;
// 当进程所引用的 Service 组件死亡时,Driver 会向该进程发送死亡通知。将死亡通知工作加入到 delivered_death list 中。表示 Driver 正在向进程发送死亡通知。
// 当进程收到死亡通知后,会通知 Driver,Driver 会将对应的死亡通知工作项从 delivered_death 中删除。
int max_threads; // Driver 可以主动请求进程注册的线程的最大数量
int requested_threads; // Driver 主动请求进程注册线程时,+1, 进程响应该请求后,-1
int requested_threads_started; // 进程响应 主动请求进程注册线程 后,+1,表示 Driver 已经主动注册了多少个线程
int tmp_ref;
struct binder_priority default_priority;
// 进程的优先级。当线程处理一个工作项时,可能设置为宿主进程的优先级,即 default_priority。因为 线程 代表其 进程 来处理 一个工作项。
struct dentry *debugfs_entry;
struct binder_alloc alloc; // binder_buffer 的 管理器
struct binder_context *context;
spinlock_t inner_lock;
spinlock_t outer_lock;
};
/**
* 可以延迟执行的工作项:
* close binder 时,释放 binder_proc, binder_node, binder_ref会比较耗时,可以创建一个 BINDER_DEFERRED_RELEASE 事务来延迟执行。
*/
binder_thread
binder_thread 描述 binder thread pool 中的 thread
struct binder_thread {
struct binder_proc *proc; // thread 所属的 process
struct rb_node rb_node; // binder_proc 通过 该变量 组织所有的 threads
struct list_head waiting_thread_node; // binder_proc 通过 该变量 组织所有的 处于等待状态的 threads
int pid; // 线程描述符
int looper; /* only modified by this thread */ // 线程状态
bool looper_need_return; /* can be written by other thread */
struct binder_transaction *transaction_stack; // 由该线程处理的 事务堆栈
struct list_head todo; // list of work to do for this thread; 当 Client 进程的请求要指定某一线程处理时,加入到 todo list 中,并且唤醒线程
struct binder_error return_error; // transaction errors reported by this thread (only accessed by this thread)
struct binder_error reply_error; // transaction errors reported by target thread
wait_queue_head_t wait; // wait queue for thread work
struct binder_stats stats; // per-thread statistics
atomic_t tmp_ref; // temporary reference to indicate thread is in use
bool is_dead; // thread is dead and awaiting free
// when outstanding transactions are cleaned up
struct task_struct *task; // struct task_struct for this thread
};
/*
* 事务依赖:
* 当 Binder 线程 在处理事务 T1 并需要依赖于其他 Binder 线程来处理事务 T2 时,他就会睡眠在由 wait 描述的等待队列中,直到 T2 处理完为止.
*/
// 用来描述线程的状态
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_POLL = 0x20,
};
/*
1. 当线程是应用程序主动注册的,通过命令 BC_ENTER_LOOPER 通知 Driver,该线程可以处理通信请求了,并将线程状态设置为 BINDER_LOOPER_STATE_ENTERED
2. 当线程是 Driver 请求注册的,通过 BC_REGISTER_LOOPER 通知 Driver 该线程可以处理通信请求了,并将线程状态设置为 BINDER_LOOPER_STATE_REGISTERED
3. 当线程处于空闲状态时,为 BINDER_LOOPER_STATE_WAITING
4. 当一个线程退出时,会通过 BC_EXIT_LOOPER 通知 Driver 将线程状态设置为 BINDER_LOOPER_STATE_EXITED。
5. 当线程处于异常状态时,为 BINDER_LOOPER_STATE_INVALID。
*/
binder_transaction
描述进程间通讯过程,这个过程又称为一个 事务.
struct binder_transaction {
int debug_id;
struct binder_work work;
/*
* 当 Binder Driver 为目标进程或目标线程创建一个 事务 时,就会将该事务的成员变量 work 设置为 BINDER_WORK_TRANSACTION ,
* 并且将它添加到目标进程或目标线程的 todo list 中等待处理.
*/
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; // 指向 Drvier 为该事务分配的 buffer
unsigned int code; // 从 binder_transaction_data 中拷贝
unsigned int flags; // 从 binder_transaction_data 中拷贝
struct binder_priority priority;
struct binder_priority saved_priority;
// 一个线程处理事务时,需要Driver修改它的线程优先级,以满足源线程和目标Service的要求。Driver在修改之前,会将之前的 优先级 保存到 saved_priority 中。
// 目标线程处理一个事务时,线程优先级不能低于目标 Service 所要求的优先级,也不能低于源线程的优先级。这时 Driver 会将这二者中的较大值设置为目标线程的优先级
bool set_priority_called;
kuid_t sender_euid;
/**
* @lock: protects @from, @to_proc, and @to_thread
*
* @from, @to_proc, and @to_thread can be set to NULL
* during thread teardown
*/
spinlock_t lock;
};
binder_write_read
通过 BINDER_WRITE_READ 命令附带结构体
struct binder_write_read {
binder_size_t write_size; /* bytes to write */
binder_size_t write_consumed; /* bytes consumed by driver */
binder_uintptr_t write_buffer;
binder_size_t read_size; /* bytes to read */
binder_size_t read_consumed; /* bytes consumed by driver */
binder_uintptr_t read_buffer;
};
// write_buffer: 表示从 Userspace -> KernelSpace 的数据
// read_buffer: 表示从 KernelSpace -> Userspace 的数据
write_buffer 和 read_buffer 的数据格式:
=================================================================================
| | | | |
| Code-1 | Content of Code-1 | Code-2 | Content of Code-2 |
| | | | |
=================================================================================
协议代码分为:命令协议代码和返回协议代码。
binder_driver_command_protocol
enum binder_driver_command_protocol {
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, __s32),
/*
* 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, binder_uintptr_t),
/*
* void *: ptr to transaction data received on a read
*/
BC_INCREFS = _IOW('c', 4, __u32),
BC_ACQUIRE = _IOW('c', 5, __u32),
BC_RELEASE = _IOW('c', 6, __u32),
BC_DECREFS = _IOW('c', 7, __u32),
/*
* 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_handle_cookie),
/*
* int: handle
* void *: cookie
*/
BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15,
struct binder_handle_cookie),
/*
* int: handle
* void *: cookie
*/
BC_DEAD_BINDER_DONE = _IOW('c', 16, binder_uintptr_t),
/*
* void *: cookie
*/
BC_TRANSACTION_SG = _IOW('c', 17, struct binder_transaction_data_sg),
BC_REPLY_SG = _IOW('c', 18, struct binder_transaction_data_sg),
/*
* binder_transaction_data_sg: the sent command.
*/
};
-
BC_TRANSACTION 和 BC_REPLY 的通信数据用 binder_transaction_data 来描述。
当 源进程 请求请求执行某一操作时,使用 BC_TRANSACTION 命令传递通信数据到目标进程。
当 目标进程 处理完请求后,通过 BC_REPLY 命令 将返回数据传递到 源进程。 -
BC_FREE_BUFFER:
通信数据为 整数,指向了 Binder Driver 的 内核缓冲区。
当 Driver 通过 内核缓冲区 将 源进程 的通信数据传递到 目标进程 后,当目标进程处理完通信请求后,可以通过协议命令 BC_FREE_BUFFER 请求 Driver 释放这个内核缓冲区。 -
BC_INCREFS ,BC_ACQUIRE ,BC_RELEASE ,BC_DECREFS :
通信数据为 整数,描述了 binder_ref 的 desc。
BC_INCREFS, BC_DECREFS 用来请求增加和减少一个 binder_ref 的弱引用计数。
BC_ACQUIRE, BC_RELEASE 用来请求增加和减少一个 binder_ref 的强引用计数。
-
BC_INCREFS_DONE, BC_ACQUIRE_DONE:
通信数据:binder_ptr_cookie
当 Binder Driver 第一次增加 binder_node 的 强引用计数或者弱引用计数时,会使用 BR_ACQUIRE, BR_INCREFS 来请求 Server 进程 增加对应的 Service 组件的 强引用计数或者弱引用计数。当 Server 进程处理完这两个请求后,就会分别使用命令协议代码 BC_INCREFS_DONE, BC_ACQUIRE_DONE 将操作结果返回给 Binder Driver。
-
BC_REGISTER_LOOPER, BC_ENTER_LOOPER, BC_EXIT_LOOPER:
无通信数据。
BC_REGISTER_LOOPER 通知 Driver , Driver 主动请求注册的 线程 处于 就绪 状态。
BC_ENTER_LOOPER 通知 Driver , 进程自己注册的 线程 处于 就绪 状态。
BC_EXIT_LOOPER 通知 Drvier ,该 线程 退出,不再接收请求。
-
BC_REQUEST_DEATH_NOTIFICATION, BC_CLEAR_DEATH_NOTIFICATION
通信数据:binder_ptr_cookie
注册死亡通知 和 注销死亡通知
-
BC_DEAD_BINDER_DONE:
通信数据:void 指针
使用该命令通知 Drvier 已处理完 Service 组件的死亡通知了。
binder_driver_return_protocol
enum binder_driver_return_protocol {
BR_ERROR = _IOR('r', 0, __s32),
/*
* 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.
*/
/*
* Client 请求 Service 时,Driver 使用 BR_TRANSACTION 通知 Server 处理该请求。
* 当 Server 处理完该请求时, 使用 BR_REPLY 返回请求结果给 Client。
*/
BR_ACQUIRE_RESULT = _IOR('r', 4, __s32),
/*
* 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), // BC_TRANSACTION, BC_REPLY的返回命令,通知源进程命令已接收,正在处理
/*
* 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), // 增加 Service 组件的 弱引用计数
BR_ACQUIRE = _IOR('r', 8, struct binder_ptr_cookie), // 增加 Service 组件的 强引用计数
BR_RELEASE = _IOR('r', 9, struct binder_ptr_cookie), // 减少 Service 组件的 弱引用计数
BR_DECREFS = _IOR('r', 10, struct binder_ptr_cookie), // 减少 Service 组件的 强引用计数
/*
* 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), // 通知 进程 执行一个 空操作,目的是方便以后可以接收返回协议代码 BR_SPAWN_LOOPER
/*
* 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), // Drvier 主动请求 进程 增加新的线程来处理通信请求
/*
* No parameters. The driver has determined that a process has no
* threads waiting to service incoming 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, binder_uintptr_t), // 死亡通知 Client
/*
* void *: cookie
*/
BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, binder_uintptr_t), // Client 请求注销 死亡通知后,使用该命令通知 Client 进程
/*
* void *: cookie
*/
BR_FAILED_REPLY = _IO('r', 17), // 当 BC_TRANSACTION 异常时,使用该命令通知 源进程
/*
* The the last transaction (either a bcTRANSACTION or
* a bcATTEMPT_ACQUIRE) failed (e.g. out of memory). No parameters.
*/
};
-
BR_ERROR
通信数据: 整数(错误代码)
Binder Driver 处理请求时异常,使用 BR_ERROR 通知应用程序. -
BR_OK
通信数据: 无
Binder Driver 成功处理了请求,使用 BR_OK 通知应用程序. -
BR_TRANSACTION, BR_REPLAY
通信数据: binder_transaction_data
Client 请求 Service , Driver 使用 BR_TRANSACTION 通知 Service 进程处理该请求.
Service 处理完了请求, Drvier 使用 BR_REPLY 给 Client 进程返回结果. -
BR_DEAD_REPLY:
通信数据: 无
Drvier 处理请求时,发现目标进程或目标线程已经死亡,使用 BR_DEAD_REPLY 通知源进程. -
BR_TRANSACTION_COMPLETE:
通信数据: 无
Driver 接收到 BC_TRANSACION 或这 BC_REPLY 时,使用 该命令 通知应用程序,命令代码已被接收,正在发给目标进程或目标线程. -
BR_INCREFS, BR_ACQUIRE, BR_RELEASE, BR_DECREFS:
通信数据: binder_ptr_cookie
BR_INCREFS, BR_DECREFS 增加/减少 Service 组件的 弱引用计数.
BR_ACQUIRE, BR_RELEASE 增加/较少 Service 组件的 强引用计数. -
BR_NOOP:
空操作
为了方便以后可以替换为 BR_SPAWN_LOOPER -
BR_SPAWN_LOOPER:
通信数据: 无
Drvier 发现没有进程没有足够的线程处理请求时,使用该命令来通知进程增加一个新的线程到 Binder 线程池 中. -
BR_DEAD_BINDER, BR_CLEAR_DEATH_NOTIFICATION_DONE:
通信数据: void 指针, 指向 Service 组件死亡通知的对象地址.
当 Drvier 监测到 Service 死亡时,使用 BR_DEAD_BINDER 通知 Client 进程.
当 Client 进程通知 Driver 注销之前注册的死亡通知时, Drvier 指向完这个注销操作后,使用 BR_CLEAR_DEATH_NOTIFICATION_DONE 通知 Client 进程.
binder_ptr_cookie
// 描述 Binder 实体对象 或 死亡通知
struct binder_ptr_cookie {
binder_uintptr_t ptr;
binder_uintptr_t cookie;
};
/*
当 描述 binder_node 时,ptr 和 cookie 等同于 binder_node 的 ptr 和 cookie
*/
/*
当 描述 Service 组件的死亡通知时, ptr 指向 binder_ref 的 desc,cookie 指向 接收死亡通知的 对象地址
*/
binder_transaction_data
用来描述进程间通信所传输的数据
struct binder_transaction_data {
/* The first two are only used for bcTRANSACTION and brTRANSACTION,
* identifying the target and contents of the transaction.
*/
union {
/* target descriptor of command transaction */
__u32 handle; // 如果目标是 binder_ref, handle 表示 binder_ref 的 desc
/* target descriptor of return transaction */
binder_uintptr_t ptr; // 如果目标是 binder_node ,ptr 指向 binder_node 对应的 Service 组件的 弱引用计数对象(weakref_impl) 的地址
} target;
binder_uintptr_t cookie; /* target object cookie */
// 当 执行 BR_TRANSACTION 时有意义,指向目标 Service 组件的地址
__u32 code; /* transaction command */
// code 是 用户命令,Drvier 并不关心
/* General information about the transaction. */
__u32 flags;
// flags 描述通信特征
/*
enum transaction_flags {
TF_ONE_WAY = 0x01, /* 单向,异步,无返回值 */
TF_ROOT_OBJECT = 0x04, /* contents are the component's root object */
TF_STATUS_CODE = 0x08, /* 表示 data 成员变量描述的数据缓冲区是一个 4字节的状态码 */
TF_ACCEPT_FDS = 0x10, /* 源进程不允许目标进程返回的结果数据中包含文件描述符 */
};
*/
pid_t sender_pid;
uid_t sender_euid;
binder_size_t data_size; /* number of bytes of data */
binder_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 */
binder_uintptr_t buffer;
/* offsets from buffer to flat_binder_object structs */
binder_uintptr_t offsets;
} ptr; // 数据较大时,需要动态分配内存,由 ptr 描述
__u8 buf[8]; // 数据较小时,使用 buf 来传递数据
} data;
};
/*
* ptr 说明:
* 当 buffer 指向的数据中包含 Binder 对象时,那么 offsets 数组 用来描述 Binder 对象的位置。
* 有了这个偏移数组后,Drvier 维护 binder_node 和 binder_ref 的引用计数
*/
| | |
|------------------------------------data_size---------------------------------|-----------offset_size-----------|
|---------------------------n2----------------------| | |
|-------n1--------| | | |
|================================================================================================================|
| | | | | | |
| ...... | flat_binder_object | ... | flat_binder_obejct | n1 | n2 |
| | | | | | |
|================================================================================================================|
| |
| |
data.ptr.buffer |
data.ptr.offsets
falt_binder_object
// 描述 binder 实体对象
// 描述 binder 引用对象
// 描述 文件描述符
struct flat_binder_object {
struct binder_object_header hdr;
__u32 flags;
/* 8 bytes of data. */
union {
binder_uintptr_t binder; /* local object */ // 描述 binder 实体对象,指向 Service 组件内部弱引用计数对象(weakref_impl) 的地址
__u32 handle; /* remote object */ // 描述 Binder 引用对象,binder 引用对象的 句柄
};
/* extra data associated with local object */
binder_uintptr_t cookie; // 指向 Service 组件的地址
};
enum {
BINDER_TYPE_BINDER = B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE), // Binder 实体对象
BINDER_TYPE_WEAK_BINDER = B_PACK_CHARS('w', 'b', '*', B_TYPE_LARGE), // Binder 实体对象
BINDER_TYPE_HANDLE = B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE), // Binder 引用对象
BINDER_TYPE_WEAK_HANDLE = B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE), // Binder 引用对象
BINDER_TYPE_FD = B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE), // 文件描述符
BINDER_TYPE_FDA = B_PACK_CHARS('f', 'd', 'a', B_TYPE_LARGE), //
BINDER_TYPE_PTR = B_PACK_CHARS('p', 't', '*', B_TYPE_LARGE), //
};
``
网友评论