Android Binder 机制初步学习 笔记(一)—— 概述及数据结构介绍

本文是Android Binder机制的学习笔记,主要介绍了Binder的基础数据结构,包括binder_work、binder_node等结构体,阐述了Binder如何提高进程间通讯效率。分析来源于《Android系统源代码情景分析(修订版)》,并讲解了Binder机制的关键优势和组成部分。
摘要由CSDN通过智能技术生成


NOTE

  • 源码版本:Android 7.1.2。
  • 内核版本:android-goldfish-3.4
  • 内核下载:git clone https://aosp.tuna.tsinghua.edu.cn/kernel/goldfish.git (清华镜像站)
  • 以下分析思路均来自老罗的《Android 系统源代码情景分析(修订版)》

Binder 机制简介

  • Linux 内核提供了多种进程间通讯机制:
    • Pipe:管道。
    • Signal:信号。
    • Message:消息队列。
    • Share Memory:共享内存。
    • Socket:插口。
  • Android 虽是基于 Linux 内核而开发的,但并没有采用这些传统通讯机制,而是自己开发了一套新的机制,即 Binder
  • Binder 优势:
    • 进程间传输数据时仅执行一次拷贝操作。
    • 因此提高了效率,同时节省了空间。
  • Binder 机制中的关键词:
    1. OpenBinderBinder 机制是在它的基础上实现的。(Wiki:OpenBinder
    2. CS 通讯方式:客户端 Client / 服务端 Server
    3. Server 进程:提供服务 Service 的进程。
    4. Client 进程:访问服务的进程。
    5. Service 组件:同一个 Server 可以运行多个组件向 Client 提供服务,提供服务的组件即 Service 组件。
    6. Service 代理对象:同一个 Client 可以同时向多个 Server 请求服务,每个请求都对应有一个 Client 组件,这个组件即是 Service 代理对象。
    7. Binder 线程池:每个 ServerClient 进程都会维护一个 Binder 线程池来处理进程间通讯请求,service 的提供与访问是可并发的。
    8. Binder 驱动程序:向用户空间暴露一个设备文件 /dev/binder,使应用程序进程可以间接通过它建立通信通道。
    9. Service Manager 组件
      • Service 组件启动,就会将自己注册到一个 Service Manager 中,以便 Client 组件可以找到它。
      • 可称为 Binder 机制的上下文管理者。
      • 可看做一个特殊的 Service 组件。
    10. open:系统接口,用于打开 Binder 设备。
    11. mmap:系统接口,提供内存映射操作。
    12. ioctl:系统接口,提供内核缓冲区管理操作,可实现读、写功能。
  • ClientServiceService ManagerBinder 关系:
    1. ClientServiceService Manager 运行在用户空间。
    2. Binder 驱动程序运行在内核空间。
    3. 系统提供 Service ManagerBinder
    4. ClientService 由应用程序实现。
    5. 通过 openmmapioctlBinder 设备交互。

@图 1. 关系图


Binder 基础数据结构分析

  • NOTE
    • 结构体中经常能看到成员变量 debug_id ,它是用来标识 Binder 实体对象身份,帮助调试 Binder 驱动的,下面的分析中这个就忽略掉。
    • 数据结构介绍的部分内容比较多,我觉得在这部分,不用一开始就一一理清楚它们的详细用处,只需要大概了解每个结构体的用处就好。等到以后分析实现机制的时候,碰到不太了解的成员变量时再回头来看,这样能理解得比较深刻。

1. binder.c

  • 位置:kernel/goldfish/drivers/staging/android/binder.c
  • 该文件中的结构体都是在 Binder 驱动程序内部进行使用的。
1.1 struct binder_work
struct binder_work {
        struct list_head entry;
        enum {
                BINDER_WORK_TRANSACTION = 1,
                BINDER_WORK_TRANSACTION_COMPLETE,
                BINDER_WORK_NODE,
                BINDER_WORK_DEAD_BINDER,
                BINDER_WORK_DEAD_BINDER_AND_CLEAR,
                BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
        } type;
};
  • binder_work 结构用于描述待处理的工作项
  • 工作项有可能属于一个进程,也可能属于某个线程。
  • 成员变量
    1. entry:将该结构体嵌入到一个宿主结构中。
    2. type:描述工作项类型,可判断出该结构嵌入的宿主类型。
1.2 struct binder_node
struct binder_node {
        int debug_id;
        struct binder_work work;
        union {
                struct rb_node rb_node;
                struct hlist_node dead_node;
        };
        struct binder_proc *proc;
        struct hlist_head refs;
        int internal_strong_refs;
        int local_weak_refs;
        int local_strong_refs;
        void __user *ptr;
        void __user *cookie;
        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;
        unsigned min_priority:8;
        struct list_head async_todo;
};
  • binder_node 结构描述一个 Binder 实体对象
  • 每个 Service 组件在驱动中都对应一个 Binder 实体,描述它在内核中的状态。
  • Binder 驱动通过强 (弱)引用计数技术维护实体的生命周期。
  • 成员变量
    1. work:即工作项。
    2. proc:指向一个 Binder 实体对象的宿主进程。
    3. rb_node:宿主进程用红黑树维护内部 Binder 实体,该变量则是红黑树中一个节点。
    4. dead_node:宿主进程死亡,这个 Binder 实体就通过该变量保存在全局 hash 表中。
    5. ref
      • 一个 Binder 实体可被多个 Client 组件引用,于是驱动用 binder_ref 结构描述这些引用关系。
      • 将引用同一个 Binder 实体的所有引用保存在 hash 表中。
      • 该成员变量用于描述这个 hash 表。
      • 驱动通过它可知哪些 Client 组件引用了同一 Binder 实体。
    6. internal_strong_refs && local_strong_refs:描述强引用计数。
    7. local_weak_refs:描述弱引用计数。
    8. has_strong_ref && has_weak_ref
      • 一个 Binder 实体请求一个 Service 执行某一操作,则增加该 Service 组件的强(弱)引用计数。
      • 相应地,Binder 实体将它的这两个变量置为 1
    9. pending_strong_ref && pending_weak_ref
      • 1 时,表明正处于 Binder 实体向 Service 组件请求改变引用计数的过程
      • 0 时,表明上述过程结束
    10. ptr && cookie:指向用户空间地址。
      • ptr 指向 Service 组件内部引用计数对象(weakref_impl 类型)地址。
      • cookie 指向该 Service 组件地址。
    11. has_async_transaction:描述 Binder 实体是否正在处理异步事务。(1 为是, 0 为否)
    12. async_todo
      • 异步事务队列。
      • 异步事务优先级低于同步,表现为同同一时刻,一个 Binder 实体所有异步事务至多处理一个,其余等待。而同步事务无限制。
    13. min_priority:处理来自 Client 的请求时,所要求的处理线程(Server 中的一个线程)应具备的最小线程优先级。
    14. accept_fds:表示是否可接收包含文件描述符的通讯数据(1 可以,0 不可)。
1.3 struct binder_ref_death
struct binder_ref_death {
        struct binder_work work;
        void __user *cookie;
};
  • binder_ref_death 用来描述一个 Service 组件的死亡接收通知:
    • Service 组件所在进程可能会意外崩溃。
    • Client 进程需要在引用的 Service 组件死亡时得到通知,以便做出相应处理。
  • 驱动决定向 Client 发送组件死亡通知时,将该结构体封装成一个工作项,并设置相应 work 值,再加入到 Clienttodo 队列中等待处理。
  • 成员变量
    1. work:标志一个具体的死亡通知类型。
    2. cookie:保存负责接收死亡通知的对象地址。
1.4 struct binder_ref
struct binder_ref {
        /* Lookups needed: */
        /*   node + proc => ref (transaction) */
        /*   desc + proc => ref (transaction, inc/dec ref) */
        /*   node => refs + procs (proc exit) */
        int debug_id;
        struct rb_node rb_node_desc;
        struct rb_node rb_node_node;
        struct hlist_node node_entry;
        
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值