Binder学习-驱动与架构

2025-06-17

Binder学习-驱动

Binder 数据结构

数据结构 成员变量
binder_ref - rb_node_desc 按句柄值排序的红黑树节点
- rb_node_node 按binder实体地址排序的红黑树节点
- proc binder引用对象的宿主进程
- node binder实体
- desc 句柄值
- death 死亡接受通知
binder_ref_death - work 工作状态
- cookie(__user) 负责接收死亡通知的对象的地址
binder_node - work 工作状态
- rb_node/ dead_node 宿主维护的binder实体红黑树节点/ 全局宿主进程死亡的hash列表
- proc 宿主进程
- ptr(__user)Service组件的引用计数对象(weakref_impl)
- cookie (__user) Service组件地址
- has_async_transaction 是否有异步事务
- accept_fds 是否接受文件描述头
- min_priority 最低优先级
- async_todo 异步事务队列
binder_buffer - entry 内核缓冲区节点
- rb_node 进程的空闲 entry 红黑树节点(大小)/ 已分配的buffer entry 红黑树节点(地址)
- free 是否空闲
- allow_user_free 是否允许用户空间释放buffer
- transaction 处理的事务
- target_node 处理buffer的binder
- data_size buffer中的数据大小
- offsets_size buffer中传输的binder的偏移量数组
- data 指向数据缓冲区
binder_proc - proc_node 全局binder_proc散列表中的节点
- buffer_size/buffers 全部缓冲区的大小/缓冲区列表的头部指针
- free_buffers/ allocated_buffers/ free_async_space 空闲内存红黑树/ 分配内存红黑树/ 用来保存异步事务数据的内核缓冲区大小
- vma/ user_buffer_offset 其中保存buffer在用户空间中地址/ 保存用户空间地址与内核空间地址之间的差值
- pages struct pages*的数组,每个元素指向物理页面
- threads/ max_threads/ ready_threads 以红黑树(线程ID)组织的Binder线程池/ Binder驱动程序最多可以主动请求进程注册的线程数量/ 进程当前的空闲Binder线程数量
- requested_threads/ requested_threads_started Binder正在主动请求注册的线程的数量/ Binder已经主动请求注册的线程数量
- todo/ wait 进程的待处理工作项队列/ 空闲Binder线程
- default_priority 默认优先级
- nodes/ refs_by_desc/ refs_by_node Binder实体的红黑树/ Binder引用句柄的红黑树/ Binder引用按binder实体组织的红黑树
- deferred_work_node 进程可以延迟执行的工作项的散列表(BINDER_DEFERRED_PUT_FILES 在进程不再需要Binder通信时,关闭相应的文件描述符并释放内核缓冲区时创建的工作项 | BINDER_DEFERRED_FLUSH 唤醒wait中的线程创建的工作项 | BINDER_DEFERRED_RELEASE 进程通过close关闭设备文件/dev/binder 时创建 )
- delivered_death Service组件死亡通知
binder_thread - proc 宿主进程
- rb_node proc中thread红黑树的节点
- pid/ looper 标识binder的状态
- todo 请求线程处理的client进程请求
- transaction_stack Binder交给线程的事务的栈(binder_transaction类型)
- wait 线程执行事务时等待其依赖的其他事务完成时所在的等待队列
- return_error/ return_error2 错误
binder_transaction - from/ to_proc/ to_thread 发起事务的线程/ 处理事务的进程/ 处理事务的线程
- priority / sender_id/ saved_priority 源线程优先级/ 用户ID/ 保存被修改的线程优先级
- buffer 事务的内核缓冲区
- from_parent/ to_parent 事务依赖的另一个事务/ 目标线程中当前事务后需要处理的事务

Binder与用户程序通信的数据结构

数据结构 成员变量 作用
binder_write_read - write_size/write_consumed/write_buffer
输入数据的长度/ 驱动已读的长度/ 输入缓冲区的起始地址
- read_size/ read_consumed/ read_buffer
返回的数据长度/ 用户空间已读的长度/ 输出缓冲区的其实地址
通信所传输的数据
BinderDriverCommandProtocol   命令协议
BinderDriverReturnProtocol   返回协议
binder_transaction_data   进程间传输的数据
flat_binder_object   描述Binder实体,Binder引用对象或一个文件描述符

Binder初始化

  1. binder_init 在/proc下创建/binder/proc目录,并创建state, stats, transaction_log, failed_transaction_log五个文件,通过misc_register创建Binder设备
  2. 指定binder的file_operations,定义binder设备miscdevice

Binder文件操作

打开Binder设备文件

  1. 创建binder_proc结构体proc,初始化tsk, default_priority, pid,并加入到binder_procs
  2. proc保存到filp的private_data中,用于binder驱动程序获取proc
  3. 创建以PID为名的文件,用于获取进程对应的Binder信息

内存映射

  1. vma指向的用户地址空间进行检查,包括其范围(vma_end-vma_start)截断为4M,是否可写(vm_flags & FORBIDDEN_MMAP_FLAGS需为0) ,并设置VM_DONTCOPY为1,VM_MAYWRITE位设置为0,判断proc->buffer是否已经分配
  2. 调用get_vm_area在内核中分配空间,并将其地址与大小保存在proc中,指定其打开和关闭函数
  3. 分配一个空间保存proc->pages指向的数组,分配一个物理页面给proc->buffer,(通过binder_update_page_range)创建链表proc->buffers并将buffer加入,设置buffer空闲并加入到空闲buffer红黑树中,设置给异步事务的空间大小为buffer_size/2

内核缓冲区管理

内核缓冲区分配

发送BC_TRANSACTION, BC_REPLY

binder_alloc_buf

  1. data_size, offsets_size 的合法性检验,异步事务缓冲区大小检验
  2. 在红黑树中查找第一个大于等于需要的size的buffer
  3. 对buffer进行裁剪(若剩余部分大于等于一个struct binder_buffer+4字节,则进行裁剪,否则不进行裁剪),并为其分配物理页面
  4. 将buffer从空闲内核缓冲区删除,并加入到已分配物理页面的内核缓冲区红黑树中
  5. 将裁剪后剩余的空间封装为另一个new_buffer并加入到内核缓冲区列表和空闲缓冲区红黑树中
  6. 设置buffer的数据缓冲区和偏移数组缓冲区大小,并设置其是否用于异步事务

内核缓冲区释放

进程处理完BR_TRANSACTION, BR_REPLY

binder_free_buf

  1. 计算需要释放的buffer的大小
  2. 释放物理页面,并从已分配物理页面的buffer红黑树中删除:
  3. 合并前后两个空闲buffer,方法为删除buffer,将其所占用的空间追加到前一个空闲内核缓冲区中

内核缓冲区查询

binder_buffer_lookup

s