Binder
Binder学习日志(updating)
5.27
用户空间和内核空间
Binder
通常意义下,Binder指的是一种通信机制;我们说AIDL使用Binder进行通信,指的就是Binder这种IPC机制。
对于Server进程来说,Binder指的是Binder本地对象
对于Client来说,Binder指的是Binder代理对象,它只是Binder本地对象的一个远程代理;对这个Binder代理对象的操作,会通过驱动最终转发到Binder本地对象上去完成;对于一个拥有Binder对象的使用者而言,它无须关心这是一个Binder代理对象还是Binder本地对象;对于代理对象的操作和对本地对象的操作对它来说没有区别。
对于传输过程而言,Binder是可以进行跨进程传递的对象;Binder驱动会对具有跨进程传递能力的对象做特殊处理:自动完成代理对象和本地对象的转换。在驱动中,Binder本地对象的代表是一个叫做binder_node的数据结构,Binder代理对象是用binder_ref代表的
Binder 驱动中通过 static HLIST_HEAD(binder_procs);,创建了全局的哈希链表 binder_procs,用于保存所有的 binder_proc 队列,每次新创建的 binder_proc 对象都会加入 binder_procs 链表中
Binder_mmap
虚拟地址被转换为物理地址要有页表
通过加🔒的形式保证每次只分配一个进程的内存。保证多进程的并发访问,user_buffer_offset 是虚拟进程地址与虚拟内核地址的差值
当内核地址为 kernel_addr,则进程地址为 proc_addr = kernel_addr + user_buffer_offset
Binder_update_page_range
用于分配物理空间,将物理空间分别映射到内核空间和进程空间,特定参数情况下也可以释放物理空间
其中binder_delete_free_buffer用于释放分配的内存 主要用于防止内存泄漏
binder_free_buf用于释放缓存区的内存 因为进行进程间通信的时候会频繁的分配和释放内存 所以弄一个缓存区
Binder_alloc_buf
结构体:用户定义的数据类型 可以包含多种数据类型 用struct定义 tag为标志 list为成员列表
5.28
Binder_ioctl
Binder_get_thread
Binder_ioctl_write_read
工作流程图
用bwr写入缓存 如果有数据则执行binder_thread_write 写入失败则将数据写回用户空间并退出
用bwr读取缓存 如果有数据则执行binder_thread_read 读取失败则将数据写回用户空间并退出
将内核数据(bwr)拷贝回用户空间(unuf)
守护线程和用户线程
守护线程
守护线程用于服务其它线程,垃圾回收线程就是最经典的守护线程
可以理解为后台服务的线程 如四大组件的service 注意的是这个并不是必须的线程
可以通过setDaemon(true)去创建守护线程
用户线程
用户自定义的线程
当所有非守护线程结束之后 会退出jvm 只要有非守护线程的时候则不会退出jvm
当在守护线程之中产生新的线程 默认为守护线程 用户线程也是一样的
Binder架构
Service manager用于管理各种服务 比较重要
client端:BpBinder.transact()来发送事务请求;
server端:BBinder.onTransact()会接收到相应事务。
6.3
常用命令场景
binder_write_read (读写交互)
binder_set_context_mgr (service 进程成为上下文管理者)
binder_version(初始化processstate对象)
Binder相关重要结构体
binder_proc
binder进程
进程调用open()打开binder驱动都会创建 用于管理进程间通信的相关信息
binder_thread
binder线程
对应上层的binder线程
上层线程:应用线程 这里的binder线程为binder驱动线程 上层线程就是应用线程
binder_node
binder实体
对于binder对象 记录BBinder的进程,指针,引用计数
binder_ref
binder引用
对应Bpbinder对象 记录Bpbinder(S)的引用计数 死亡通知 BBinder(S)的指针
binder_ref_death
Binder死亡引用
记录死亡信息
binder_write_read
binder读写操作
记录buffer(缓冲区 属于内存)读写的数据信息
binder_transaction_data
binder事务数据
记录传输数据 如pid uid RPC
uid 是用户身份证明
pid 是进程标识符
rpc 是一种通信协议
flat_binder_object
binder扁平对象
binder对象在两个进程间传递的扁平结构
扁平结构:
binder_buffer
内存
调用mmap()创建的缓存区
binder_transaction
binder事务
记录传输事务的发送线程,进程和接受线程,进程
binder_work
binder工作
记录binder工作类型
工作类型
binder_state
binder状态
6.6
binder_proc
free_buffers:记录所有空闲的buffer,记录以buffer_size为key的binder_buffer的红黑树结构
allocated_buffers:记录所有已分配的buffer,记录以buffer_size为key的binder_buffer的红黑树结构
buffers:所有buffer的地址按从低到高都进入到buffers链表中
readly_threads:准备就绪的线程个数,往往是指进入binder_thread_read中,ready_threads是指处于休眠等待状态的线程个数,越多则代表系统越空闲
requested_threads_started:指系统已经启动的线程个数
requested_threads:是指请求的线程数 取值要么为0 要么为1
binder_thread
代表当前binder操作所在的线程
looper状态如下
enum{
BINDER_LOOPER_STATE_REGISTERED =0x01 //创建注册线程 BC_REGISTER_LOOPER
BINDER_LOOPER_STATE_ENTERED =0x02 //创建主线程 BC_ENTER_LOOPER
BINDER_LOOPER_STATE_EXITED =0x04 //已退出
BINDER_LOOPER_STATE_INVALID =0x08 //非法
BINDER_LOOPER_STATE_WAITING =0x10 //等待中
BINDER_LOOPER_STATE_NEED_RETURN =0x20 //需要返回
}
binder_node
代表一个实体
debug_id(int)->节点创建时分配,具有全局唯一性,用于调试使用
rb_node(struct rb_node)->bindet节点正常使用,union
dead_node(struct hlist_node)->binder节点已销毁
proc(struct binder_proc*)->binder进程
refs(struct hlist_head)->所有指向该节点的binder引用队列
当binder对象已销毁 但还存在该binder对象的节点引用 则采用dead_node 并加入到全局列表binder_dead_nodes
binder_noder.ptr对应于flat_binder_object.binder
binder_node.cookie对应于flat_binder_object.cookie
binder_ref
debug_id(int)->用于调试使用
rb_node_desc(struct rb_node)->以desc为索引的红黑树
rb_node_node(struct rb_node)->以node为索引的红黑树
binder引用查询方式如下
node + proc => ref(transaction)
desc + proc =>ref(transaction,inc/dec ref)
node => refs + procs(proc exit)
binder_ref_death
struct binder_ref_death{
struct binder_work work;
binder_uintptr_t cookie;
}
cookie是死亡通知BpBinder代理对象的指针