细读《深入理解 Android 内核设计思想》(四)Binder 机制 [中]

本文详细介绍了Android Binder机制中的智能指针(sp, wp)及其引用计数方式,防止循环引用问题。接着,深入剖析了binder驱动相关的重要结构体,包括ProcessState、IPCThreadState、BpBinder和BinderProxy的角色和作用。通过ServiceManager getService流程,展示了Binder如何在进程间通信。最后,阐述了Android系统中Binder机制的封装类ProcessState和IPCThreadState如何简化IPC操作。" 115095789,10535015,深入理解PHP-FPM:工作原理与配置解析,"['PHP', '后端开发', 'php-fpm', '进程管理']
摘要由CSDN通过智能技术生成

对冗余挑拣重点,对重点深入补充,输出结构清晰的精简版

  1. 智能指针
  2. binder 驱动中的结构体
  3. ProcessState
  4. IPCThreadState
  5. BpBinder
  6. BinderProxy
  7. ServiceManager getService 流程

智能指针

在 binder 相关源码可以看到 sp、wp 类型的引用:

    sp<IBinder> result = new BpBinder(handle);

    wp<IBinder> result = new BpBinder(handle);

sp 即 strong pointer 强指针引用;wp 是 weak pointer 弱指针引用。在 Java 中我们不用关心对象的销毁及内存释放,GC 机制会自动辨别回收无用对象,而智能指针就是 native 层一个小型的 GC 实现。

智能指针以引用计数的方式来标识无用对象,使用智能指针的对象需继承自 RefBase,RefBase 中维护了此对象被强引用数量和弱引用数量。

强引用 sp 重载了 “=” 运算符,在引用其他对象时将强引用计数 +1,在 sp 析构函数中将强引用计数 -1,当强引用计数减至 0 时销毁引用的对象。这样就实现了对象的自动释放,但若只靠强引用计数方式,会存在循环引用的问题,导致对象永远无法被释放,弱引用就是专门用来解决循环引用问题的。

若在 A 中强引用了 B,那 B 需要引用 A 时就使用弱引用,当判断对象是否无用时仅考虑强引用计数是否为 0,不关心弱引用计数的数量。当 B 要访问 A 时,若发现 A 已经被销毁,那就表示 A 已经不存在了,需要进行重新创建等其他操作。

RefBase 提供了 extendObjectLifetime() 方法,可以用来设置引用计数器的规则,不同规则对删除目标对象的时机判断也是不一样的,包括以下三种规则:

OBJECT_LIFETIME_STRONG:只有在这个对象内存空间中的强计数器值为 0 的时候才会销毁对象)

OBJECT_LIFETIME_WEAK:只有在这个对象内存空间中的强计数器和弱计数器的值都为 0 的时候才会销毁对象

OBJECT_LIFETIME_MASK:不管这两个计数器是不是都为 0,都不销毁对象,即与一般指针无异,还是要自己手动去释放对象

binder 驱动相关的结构体

结构体 说明
binder_proc 描述使用 binder 的进程,当调用 binder_open 函数时会创建
binder_thread 描述使用 binder 的线程,当调用 binder_ioctl 函数时会创建
binder_node 描述 binder 实体节点,对应于一个 serve,即用户态的 BBinder 对象
binder_ref 描述对 binder 实体节点的引用,关联到一个 binder_node
binder_buffer 描述 binder 通信过程中存储数据的Buffer
binder_work 描述一个 binder 任务
binder_transaction 描述一次 binder 任务相关的数据信息
binder_ref_death 描述 binder_node 即 binder server 的死亡信息

其中主要结构体引用关系如下:

[(img-NBYcgWAG-1588466730812)(../img/binder_proc.png)]

以上结构体仅存在于 binder 驱动内部,还有一类结构体是与用户态共用的:

结构体 说明
flat_binder_object 描述在 binder IPC 过程传递的对象
binder_write_read 描述存储读写操作的数据
binder_version 描述 binder 的版本号
transaction_flags 描述事务的 flag,例如是否是异步请求,是否支持 fd
binder_transaction_data 描述一次事务的相关数据

参考: http://www.codeceo.com/article/android-binder-part-one.html

ProcessState

ProcessState 专门管理每个应用进程的 Binder 操作,同一个进程中只有一个 ProcessState 实例存在,且只在 ProcessState 对象创建时才打开 Binder 设备以及内存映射。相关代码如下:

///frameworks/native/libs/binder/ProcessState.cpp
sp<ProcessState> ProcessState::self(){
   
    Mutex::Autolock _l(gProcessMutex);
    if (gProcess != NULL) {
    //如果创建过 ProcessState 就直接返回
        return gProcess;
    }
    gProcess = new ProcessState;
    return gProcess;
}

外部统一通过 ProcessState::self() 方法获取 ProcessState,以此保证 ProcessState 的进程单例,ProcessState 的构造函数如下:

#define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))
#define DEFAULT_MAX_BINDER_THREADS 15

ProcessState::ProcessState()
    : mDriverFD(open_driver()) //打开 binder 设备
    , mVMStart(MAP_FAILED) //初始化为 MAP_FAILED,映射成功后会变更
    , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
    , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
    , mExecutingThreadsCount(0)
    , mMaxThreads(DEFAULT_MAX_BINDER_THREADS) //binder 线程最大数量
    , mStarvationStartTimeMs(0)
    , mManagesContexts(false)
    , mBinderContextCheckFunc(NULL)
    , mBinderContextUserData(NULL)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1){
   
       if (mDriverFD >= 0) {
    //已经成功打开 binder 驱动设备
           // 将应用进程一块虚拟内存空间与 binder 驱动映射,在此内存块上进行数据通信
           mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
           if (mVMStart == MAP_FAILED) {
    //映射失败处理
               ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
               close(mDriverFD);
               mDriverFD = -1;
           }
       }
}

ProcessState 的构造函数初始化了一些重要的变量,包括调用 open_driver() 打开

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值