Binder学习日志(updating)

5.27

juejin.cn

用户空间和内核空间

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

Binder_update_page_range

  • 用于分配物理空间,将物理空间分别映射到内核空间和进程空间,特定参数情况下也可以释放物理空间

  • 其中binder_delete_free_buffer用于释放分配的内存 主要用于防止内存泄漏

  • binder_free_buf用于释放缓存区的内存 因为进行进程间通信的时候会频繁的分配和释放内存 所以弄一个缓存区

Binder_alloc_buf

5.28

Binder_ioctl

Binder_get_thread

Binder_ioctl_write_read

  • 工作流程图

  1. 将用户空间(ubuf)的数据拷贝到内核空间(bwr)

  2. 用bwr写入缓存 如果有数据则执行binder_thread_write 写入失败则将数据写回用户空间并退出

  3. 用bwr读取缓存 如果有数据则执行binder_thread_read 读取失败则将数据写回用户空间并退出

  4. 将内核数据(bwr)拷贝回用户空间(unuf)

守护线程和用户线程

守护线程

用户线程

Binder架构

 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代理对象的指针