Android系统--ProcessState以及IPCThreadState

本文详细探讨了Android系统中ProcessState和IPCThreadState的角色和功能。ProcessState确保同一进程中只有一个实例,并负责Binder设备的打开和内存映射。而IPCThreadState则专注于与Binder驱动进行具体命令交互。分析了ProcessState的构造过程,包括open_driver()和mmap()方法,以及如何通过getContextObject获取IBinder对象。同时,介绍了IPCThreadState的线程单实例特性,以及其在Binder通信中的作用,如在talkWithDriver中的ioctl()调用。

ProcessState以及IPCThreadState

ProcessState是负责打开Binder节点并做mmap映射,IPCThreadState是负责与Binder驱动进行具体的命令交互。

ProcessState

  1. 实现ProcessState的主要关键点有以下几个:
    • 保证同一进程只有一个ProcessState实例,且只有在ProcessState对象建立时才打开Binder设备以及做内存映射
    • 向上层提供IPc服务
    • 与IPCThreadState分工
  2. 首先分析第一个点:
    源码位置:/frameworks/native/libs/binder/ProcessState.cpp
sp<ProcessState> ProcessState::self()
{
    if (gProcess != NULL) return gProcess;

    AutoMutex _l(gProcessMutex);
    if (gProcess == NULL) gProcess = new ProcessState;
    return gProcess;
}

可以看到,在这里也是先检查是否存在一个已经实例化的prosessstate,否则创建一个,所以获取ProcessState对象,需要通过这个self方法。
接下来需要一步步的观察这个新建的过程当中实现的原理。
3. 分析构造函数:

ProcessState::ProcessState()
    : mDriverFD(open_driver())
    , mVMStart(MAP_FAILED)
    , mManagesContexts(false)
    , mBinderContextCheckFunc(NULL)
    , mBinderContextUserData(NULL)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
{
    if (mDriverFD >= 0) {
        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
        if (mVMStart == MAP_FAILED) {
            // *sigh*
            LOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
            close(mDriverFD);
            mDriverFD = -1;
        }
#else
        mDriverFD = -1;
#endif
    }
    if (mDriverFD < 0) {
        // Need to run without the driver, starting our own thread pool.
    }
}

可以看到有两个之前学习的时候了解到了,与Binder驱动紧密相关的方法:
一个是open_driver(),另一个是下面的mmap(),也就是最终打开了Binder结点以及进行了内存块的映射。
4. 接下来分析在之前用到的获取IBinder的对象时的一个方法:getComtextObject
在这个方法中,传入了一个handel,最终得到了一个BpBinder,而这个BpBinder是Binder在Native层的代理。

IPCThreadState

代码位置:/frameworks/native/libs/binder/IPCThreadState.cpp
1. 单实例构造函数:

IPCThreadState* IPCThreadState::self()
{
    if (gHaveTLS) { 
    //当执行完第一次之后,再次运行的时候就已经有IPCThreadState实例,只需要获取就可以使用
restart:
        const pthread_key_t k = gTLS;
        IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
        if (st) return st;
        return new IPCThreadState;
    }

    if (gShutdown) {
        ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n");
        return NULL;
    }

    pthread_mutex_lock(&gTLSMutex);
    if (!gHaveTLS) {       
    //初始的gHaveTLS的值false,所以第一次调用的时候,会执行这里的代码
    //随后将gHaveTLS设置为true
        int key_create_value = pthread_key_create(&gTLS, threadDestructor);
        if (key_create_value != 0) {
            pthread_mutex_unlock(&gTLSMutex);
            ALOGW("IPCThreadState::self() unable to create TLS key, expect a crash: %s\n",
                    strerror(key_create_value));
            return NULL;
        }
        gHaveTLS = true;
    }
    pthread_mutex_unlock(&gTLSMutex);
    goto restart;
}

通过上面的方法,就能保证“线程单实例”的目的
2. 现有的调用分析顺序是:
getService@ServiceManagerProxy–>transact@BinderProxy–>transact@BpBinder–>transact@IPCThreadState
3. 不管是读取还是写入,Binder驱动都只是发挥中间人的作用,真正处理请求的还是Binder Client以及Binder Server双方。
4. 真正与Binder打交道的地方时talkWithDriver中的ioctl()

Android 的 Binder 通信机制中,`ProcessState::setThreadPoolMaxThreadCount()` 是一个关键的方法,用于设置当前进程中 Binder 线程池的最大线程数。该方法通过与 Binder 驱动程序交互来实现这一功能,并确保系统资源合理分配给 Binder 线程。 调用 `setThreadPoolMaxThreadCount(size_t maxThreads)` 时,系统会使用 `ioctl()` 函数向 Binder 驱动发送 `BINDER_SET_MAX_THREADS` 命令,并将指定的线程数传递给驱动程序。如果操作成功,则更新内部变量 `mMaxThreads`;否则返回错误信息并记录日志[^1]。 为了正确使用该方法,开发者应在初始化进程状态后尽早调用它。通常,在供应商进程或服务组件中,首先需要初始化 `ProcessState`,然后设置最大线程数以控制并发行为。例如: ```cpp #include <binder/ProcessState.h> int main() { // 初始化 ProcessState,默认情况下使用 /dev/binder android::sp<android::ProcessState> proc = android::ProcessState::self(); // 设置 Binder 线程池的最大线程数为 16 status_t result = proc->setThreadPoolMaxThreadCount(16); if (result != android::NO_ERROR) { ALOGE("Failed to set thread pool max threads: %d", result); } // 启动线程池 proc->startThreadPool(); // 主线程进入循环 android::IPCThreadState::self()->joinThreadPool(); return 0; } ``` 此外,若需在特定设备上使用不同的 Binder 驱动(如 `/dev/vndbinder`),应在调用 `setThreadPoolMaxThreadCount()` 之前先使用 `ProcessState::initWithDriver()` 指定驱动路径[^2]。示例代码如下: ```cpp #include <binder/ProcessState.h> int main() { // 使用自定义 Binder 驱动初始化 ProcessState android::ProcessState::initWithDriver("/dev/vndbinder"); // 获取单例实例 android::sp<android::ProcessState> proc = android::ProcessState::self(); // 设置线程池最大线程数 status_t result = proc->setThreadPoolMaxThreadCount(8); if (result != android::NO_ERROR) { ALOGE("Failed to set max threads: %d", result); } // 启动线程池 proc->startThreadPool(); // 进入主线程循环 android::IPCThreadState::self()->joinThreadPool(); return 0; } ``` 上述代码展示了如何在不同场景下正确调用 `setThreadPoolMaxThreadCount()` 来控制 Binder 线程池的行为,从而优化系统性能资源管理。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值