美文网首页工作生活
1.Binder 的数据结构介绍

1.Binder 的数据结构介绍

作者: Wi1ls努力努力再努力 | 来源:发表于2019-07-01 21:39 被阅读0次
struct binder_work {
  struct list_head entry;
  enum{
    BINDER_WORK_TRANSACTION = 1;
    BINDER_WORK_TRANSACTION_COMPLETE,
    BINDER_WORK_NODE,
    BINDER_WORD_DEAD_BINDER,
    BINDER_WODK_DEAD_BINDER_AND_CLEAR,
    BINDER_WORK_CLEAR_DETAH_NOTIFICATION,
  } type
};

描述一个待处理工作项;可能属于进程,可能属于某个线程。type 描述工作类型,entry 嵌入到宿主结构。根据 type 判断判断 binder_work 锁嵌入的宿主、


struct binder_node {
  int debug_id;
  struct binder_work work;
  union {
    struct rb_node rb_node;//在 binder_proc 维护binder 实体的红黑树节点
    struct hlist_node dead_node;
  };
  struct binder_proc *proc;//描述宿主进程
  struct hlist_head resf;//维护了引用了该 Binder 实体的 binder_ref 的表
  int internal_strong_refs;
  int locak_weak_refs;
  binder_uintptr_t ptr;//指向 Service 组件内部一个引用计数对象地址
  binder_uintptr_t cookie;//指向该 Service 组件地址
  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; //该Binder 实体是否可以接受包含文件描述符的通信数据
  unsigned min_priority:8; //要求的处理线程具备的最小线程优先级
  struct list_head anync_todo; //异步事件队列
}

描述一个 Binder 实体对象。每一个 Service 组件在 Binder 驱动都对应一个 Binder 实体对象来描述在内核的状态。宿主进程 binder_proc *proc 内部有一个红黑树维护进程内的所有 Binder 实体对象,节点是 rb_node。
下面的 binder_ref 来描述 Binder 实体在 Client 中的引用关系。


struct binder_ref_death {
  struct binder_work work;//保存死亡通知类型
  binder_uintptr_t cookie; //保存负责接受死亡通知的对象地址
}

描述 Service 组件的死亡接受通知。
binder_work work 取值为 BINDER_WORK_DEAD_BINDER、BINDER_WORK_CLEAR_DEATH_NOTIFICATION、BINDER_WORK_DEAD_BINDER_AND_CLEAR。
当 Binder 驱动向 Client 进程发送 Service 死亡通知时,将一个 binder_ref_death 封装为一个工作项,根据实际情况设置 work,然后将这个工作项添加到 Client 的 todo 队列。


struct binder_ref {
  int debug_id;
  struct rb_node rb_node_desc;
  struct rb_node rb_node_node;
  struct hlist_node node_entry;
  struct binder_proc *proc;  //binder 引用的宿主进程。
  struct binder_node *node; //该 ref 所引用的 Binder 实体对象
  uint32_t desc; //句柄值,描述一个 Binder 引用对象。
  int strong;
  int weak;
  struct binder_ref_death *death;
}

描述一个 Binder引用对象。同一个进程内的不同的 binder_ref 的 desc 不同。Binder 驱动根据 desc 找到 binder_ref,根据 binder_ref 找到 binder_node,根据 binder_node 找到 Service 服务。
binder_proc 用两个红黑树保存所有的 Binder 引用对象。key 分别为句柄值(desc)和 Binder 实体的地址(binder_node)。节点分别是 rb_node_desc 和 rb_node_node


struct binder_buffer {
  struct list_head entry;
  struct rb_node rb_node;

  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; // 内核缓冲区交由使用的 Binder 实体
  size_t data_size;  //数据缓冲区大小
  size_t offset_size; //偏移数组大小
  uint8_t data[0]; //大小可变的数据缓冲区,真正用来保存通信数据。
}

描述一个内核缓冲区,用以进程间传输数据。
Binder驱动为了方便管理,将分配给进程的一大块内核缓冲区划为若干小块。每一个小块就是 binder_buffer
每个使用 Binder 通信的进程在 Binder 驱动中都有一个内核缓冲区列表,节点是 entry。进程使用两个红黑树维护正在使用的内核缓冲区和空闲的内核缓冲区。红黑树的节点是 rb_node。
数据缓冲区(data_size)后有一个偏移数组(offset_size)记录数据缓冲区中 Binder 对象。


struct binder_proc {
  struct hlist_node proc_node;
  struct rb_root threads; //维护 Binder 线程池。binder_thread
  struct rb_root nodes; //维护该进程的所有Binder 实体
  struct rb_root refs_by_desc; // desc 作为 key,维护Binder引用(binder_ref)
  struct rb_root refs_by_node; //binder_ref->node 作为 key,维护 Binder(引用)
  int pid; //进程组 ID
  struct vm_area_struct *vma; //物理空间在用户空间映射的虚拟内存
  struct mm_struct *vma_vm_vm;//物理空间在内核空间映射的虚拟内存
  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; //保存该进程的 binder_buffer进程,以地址排列
  struct rb_root free_buffers; //未使用的 binder_buffer(未分配物理内存),以 binder_buffer 大小排列
  struct rb_root allocated_buffers; //正在使用的 binder_buffer(已经分配物理内存)
  size_t free_async_space; // 可以用来保存异步事务数据的内核缓冲大小

  struct page **pages;  //映射的页数
  size_t buffer_size; //内核缓冲区大小
  uint32_t buffer_free; //空闲内核缓冲区大小(free_buffers)
  struct list_head todo; //工作队列
  wait_queue_head_t wait; //空闲 Binder 线程组成的队列
  struct binder_stats stats;
  struct list_head delivered_death; //死亡通知队列
  int max_threads;
  int requested_threads;
  int requested_threads_started;
  int ready_threads; //当前进程空闲 Binder线程数目
  long default_priority;
  struct dentry *debugfs_entry;
};

描述一个正在使用 Binder 进程间通信的进程。(在进程调用 open 打开/dev/binder 时由 Binder 驱动自动创建,同时保存到一个全局 hash)
进程open dev/binder 后,mmap 映射。即请求 Binder 驱动分配一块内核缓冲区。


struct binder_thread{
  struct binder_proc *proc; //宿主进程
  struct rb_node rb_node;
  int pid;
  int looper;
  struct binder_transaction *transacton_stack; //事务堆栈
  struct list_head todo; //处理队列
  uint32_t return_error;
  uint32_t return_error_2;

  wait_queue_head_t wait;
  struct binder_stats stats; //统计 Binder 线程数据
}

描述 Binder 线程池中的一个线程。是 binder_proc 的 threads 中的节点。


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; //事务是同步的还是异步

  struct binder_buffer *buffer; //Binder 驱动为该事务分配的内核缓冲区
  unsigned int code; //
  unsigned int flags;  //
  long priority;
  //saved_priority 和 sender_euid 识别事务发起方身份
  long saved_priority; //源线程优先级
  kuid_t sender_euid; //源线程用户 ID
}

描述 Binder 通信过程,即事务。


struct binder_write_read {
  //描述输入数据,从用户空间传到 Binder 驱动
  binder_size_t wirte_size; //write_buffer 的大小,单位字节
  binder_size_t write_consumed;//表示 Binder 驱动已经处理的数据大小
  binder_uintptr_t write_buffer;//指向用户空间缓冲区,保存着数据
  //描述输出数据,从 Binder 驱动返回给用户空间
  binder_size_t read_size;//read_buffer 大小
  binder_size_t read_consumed;//指用户应用已经处理的大小
  binder_uintptr_t read_buffer;//指向一个用户空间缓冲区
}

描述进程间通信所传输的数据。
write_buffer 与 read_buffer 内数据是格式固定的数组,格式是通信协议代码及通信数据。

Code-1 Content of Code-1 Code-2 Content of Code-2 ... Code-n Content of Code-n

协议分为命令协议代码(在 write_buffer 使用)[binder_driver_command_protocol]和返回协议代码(在 read_buffer 使用)[binder_driver_return_protocol]。

enum binder_driver_command_procotol {
  //Binder 请求执行操作。源进程使用BC_TRANSACTION请求 Binder驱动 转发通信数据给目标进程
  BC_TRANSACTION = _IOW('c', 0, struct binder_transaction_data), 
  //目标进程处理完毕后,使用BC_REPLY请求 Binder驱动 转发结果数据给源进程
  BC_REPLY = _IOW('c', 1, struct binder_transaction_data),

  BC_ACQUIRE_RESULT = _IOW('c', 2, __s32),
  //目标进程处理完请求后,使用BC_FREE_BUFFER请求 Binder 驱动释放内核缓冲区
  BC_FREE_BUFFER = _IOW('c', 3, binder_uintptr_t),
  //下面 4 个的通信数据是一个 Binder 引用的句柄。用来请求 Binder 驱动增加或减少 Binder 引用的引用计数
  BC_INCREFS = _IOW('c', 4, __u32),//增加弱引用
  BC_ACQUIRE = _IOW('c', 5, __u32),//增加强引用
  BC_RELEASE = IOW('c', 6, __u32),//减少强引用
  BC_DECREFS = IOW('c', 7, __u32),//减少弱引用
 
  BC_INCREFS_DONE = _IOW('c', 8, struct binder_ptr_cookie),
  BC_ACQUIRE_DONE = _IOW('c', 9, struct binder_ptr_cookie),

  BC_ATTEMPT_ACQUIRE = _IOW('c', 10, struct binder_pri_desc),
  //Binder 驱动主动注册线程到 Binder 驱动,使用使用BC_REGISTER_LOOPER表明已经准备就绪处理通信请求了
  BC_REGISTER_LOOPER = _IO('c', 11),
  //线程将自己注册到 Binder 驱动后,使用BC_ENTER_LOOPER表明已经准备就绪处理通信请求了
  BC_ENTER_LOOPER = _IO('c', 12),
  //线程退出,表示不再接受IPC 请求
  BC_EXIT_LOOPER = _IO('c', 13),
  //注册死亡接收通知
  BC_REQUEST_DEATH_NOTIFICATION =  _IOW('c', 14, struct binder_handle_cookie),
  //注销死亡接收通知
  BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_handle_cookie),
  //通知 Binder 驱动已经处理好该 Service 死亡通知。
  BC_DEAD_BINDER_DONE = _IOW('c', 16, binder_uintptr_t),
};
enum binder_driver_return_protocol {
  BR_ERROR = _IOR('r', 0, __s32),
  
  BR_OK = _IO('r', 1),
  //当 Client 当 Service 发出请求,Binder 驱动会使用BR_TRANSACTION通知 Server 进程处理请求。
  //Server 请求返回给 Binder 驱动时,驱动使用BR_REPLY将请求结果返回给 Client 进程
  BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data),
  BR_REPLY = _IOR('r', 3, struct binder_transaction_data),

  BR_ACQUIRE_RESULT = _IOR('r', 4, __32),
  
  BR_DEAD_REPLY = _IO('r', 5),

  BR_TRANSACTION_COMPLETE = _IO('r', 6),

  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_cooike),

  BR_ATTEMPT_ACQUIRE = _IOR('r', 11, struct binder_pri_ptr_cooike),
  
  BR_NOOP = _IO('r', 12),

  BR_SPAWN_LOOPER = _IO('r', 13),
   
  BR_FINISHED = _IO('r', 14),
  
  BR_DEAD_BINDER = _IOR('r', 15, binder_uintptr_t),
  BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, binder_uintptr_t),
  BR_FAILED_REPLY = _IO('r', 17),
};
Binder 驱动转发请求
struct binder_ptr_cookie {
  binder_uintptr_t ptr;
  binder_uintptr_t cookie;
}

描述一个 Binder 实体对象或者一个 Service 组件的死亡接收通知。
当描述 Binder 实体,ptr 和 cookie 即 binder_node 的 ptr 和 cookie;
当描述 Service 组件时,ptr 指向 Binder 引用对象的句柄值,cookie 指向用来接收死亡通知的对象地址。


struct binder_transaction_data {
  union {
    __u32 handle;  //若是目标 Binder 引用对象,指向 Binder 引用句柄
    binder_uintptr_t ptr;//如果是 Binder 实体,指向 Service 内部一个弱引用计数对象地址。
  } target; //描述一个目标 Binder 对象或者目标 Binder 引用对象
  binder_uintptr_t cookie; //当 Binder 驱动使用 BR_TRANSACTION 向 Service 进程请求,才有意义,指向目标 Serveice 组件地址。
  __u32 code; //Client 与 Service 约定好的通信代码

  __u32 flags; //描述通信行为特征
  pid_t sender_pid; //发起 IPC 的进程 PID
  uid_t sender_euid;  //发起 IPC 的进程 UID
  binder_size_t data_size;  
  binder_size_t offsets_size; // 偏移数据大小

  union{
    struct {
      binder_uintptr_t buffer; //指向数据缓冲区,前面的 data_size 说明数据大小
      binder_uintptr_t offsets;  //如果数据内有 Binder对象,则数据后有偏移数组描述 Binder 对象位置。
    }  ptr;  //数据大使用 ptr
    __u8 buf[8];  //数据比较小使用 buf[8]。
  } data; //指向通信数据缓冲区。
};

描述进程间通信过程中所传输的数据。数据每个 Binder 对象对应一个 flat_binder_object 结构来描述


struct flat_binder_object {
  __u32 type; // 区别描述的是 Binder 实体还是 Binder 引用还是文件描述符
  __u32 flags; //当描述的是 Binder 实体时,有意义。低 7 位代表处理请求时的线程的最小线程优先级。第八位代表是否允许传递含文件描述符的数据(1允许)

  union {
    binder_uintptr_t binder;  //描述的是 Binder 实体时,指向 Binder 实体对应的 Service 组件内的弱引用计数对象地址。cookie 指向 Serivice 组件地址
    __u32 handle;  //  当描述的是Binder 引用时,描述 Binder 引用对象句柄
  }

  binder_uintptr_t cookie; //大概描述的是 Binder 实体时,指向 Service 组件地址
}

描述一个 Binder 实体对象,或 Binder 引用对象,或一个文件描述符。通过 type 区别。
type 类型

#define B_PACK_CHARS(c1, c2, c3, c4)  ((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4))
#define B_TYPE_LARGE 0x85

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),    //描述一个文件描述符
};

相关文章

网友评论

    本文标题:1.Binder 的数据结构介绍

    本文链接:https://www.haomeiwen.com/subject/hsggcctx.html