Android ProcessState self() init open_driver

调用流程

1. sServiceManager = ServiceManagerNative
                .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
2. BinderInternal.getContextObject())
3. static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
    return javaObjectForIBinder(env, b);
}
4. ProcessState::self()
5. sp<ProcessState> ProcessState::self()
{
    return init(kDefaultDriver, false /*requireDefault*/);
}

init

#ifdef __ANDROID_VNDK__
const char* kDefaultDriver = "/dev/vndbinder";
#else
const char* kDefaultDriver = "/dev/binder";
#endif

sp<ProcessState> ProcessState::init(const char* driver, bool requireDefault) {
    if (driver == nullptr) { //1
        std::lock_guard<std::mutex> l(gProcessMutex);
        if (gProcess) {
            verifyNotForked(gProcess->mForked);
        }
        return gProcess;
    }

    [[clang::no_destroy]] static std::once_flag gProcessOnce;
    std::call_once(gProcessOnce, [&](){ //2
        if (access(driver, R_OK) == -1) {
            ALOGE("Binder driver %s is unavailable. Using /dev/binder instead.", driver);
            driver = "/dev/binder";
        }

        if (0 == strcmp(driver, "/dev/vndbinder") && !isVndservicemanagerEnabled()) {
            ALOGE("vndservicemanager is not started on this device, you can save resources/threads "
                  "by not initializing ProcessState with /dev/vndbinder.");
        }

        // we must install these before instantiating the gProcess object,
        // otherwise this would race with creating it, and there could be the
        // possibility of an invalid gProcess object forked by another thread
        // before these are installed
        // 3
        int ret = pthread_atfork(ProcessState::onFork, ProcessState::parentPostFork,
                                 ProcessState::childPostFork);
        LOG_ALWAYS_FATAL_IF(ret != 0, "pthread_atfork error %s", strerror(ret));

        std::lock_guard<std::mutex> l(gProcessMutex);
        gProcess = sp<ProcessState>::make(driver); //4
    });

    if (requireDefault) { //5
        // Detect if we are trying to initialize with a different driver, and
        // consider that an error. ProcessState will only be initialized once above.
        LOG_ALWAYS_FATAL_IF(gProcess->getDriverName() != driver,
                            "ProcessState was already initialized with %s,"
                            " can't initialize with %s.",
                            gProcess->getDriverName().c_str(), driver);
    }

    verifyNotForked(gProcess->mForked); //6
    return gProcess;
}

一、单例模式与线程安全

​​1. 单例控制​​
当 driver == nullptr 时直接返回现有实例 gProcess,确保全局唯一性。若需要初始化新实例,通过 std::call_once 保证多线程环境下仅执行一次初始化。
2. ​​锁机制​​
使用 std::mutex 锁保护 gProcess 的访问,避免多线程竞争条件。例如,std::lock_guardstd::mutex l(gProcessMutex) 在关键代码段加锁。

二、驱动路径处理

​​1. 驱动可用性检查​​
通过 access(driver, R_OK) 验证指定驱动路径的可读性。若失败(如 /dev/vndbinder 不可用),自动回退到默认路径 /dev/binder,并记录错误日志。
​​2. vndbinder 的特殊处理​​
当尝试初始化 /dev/vndbinder 时,会额外检查 vndservicemanager 是否已启动。若未启动,输出警告日志提示资源浪费风险。

三、进程 Fork 处理

通过 pthread_atfork 注册以下回调函数,确保进程 fork 时 Binder 状态正确:

  • ​​onFork​​:fork 前执行,用于锁定资源。
  • ​​parentPostFork​​:父进程 fork 后恢复状态。
  • ​​childPostFork​​:子进程 fork 后重置 Binder 驱动连接(如关闭文件描述符)。

四、参数验证与错误处理

​​1. 驱动一致性校验​​
若 requireDefault 为 true,强制要求当前实例的驱动名称必须与传入的 driver 一致,否则触发致命错误(LOG_ALWAYS_FATAL_IF),防止重复初始化不同驱动。
​​2. Fork 状态检查​​
调用 verifyNotForked(gProcess->mForked) 确保当前进程未处于 fork 后的子进程中,避免跨进程状态污染。

五、关键对象创建

  • 实例化 ProcessState​​
    通过 sp::make(driver) 创建智能指针管理的 ProcessState 对象,其构造函数会执行以下操作:
    1. 调用 open_driver() 打开 Binder 驱动设备(如 /dev/binder)。
    2. 使用 mmap 在内核空间映射内存区域(默认大小 1MB-8KB),用于 Binder 事务传输。
    3. 通过 ioctl 设置 Binder 版本和最大线程数。

总结

此函数是 Binder 通信的基石,负责:

​​1. 单例生命周期管理​​:确保进程内唯一的 ProcessState 实例。
​​2. 驱动兼容性适配​​:动态处理不同驱动路径(标准/VND Binder)。
​​3. 多进程安全​​:通过 fork 处理回调避免状态泄漏。
​​4. 资源初始化​​:完成驱动连接、内存映射等底层操作。

通过上述机制,ProcessState::init() 为 Android 跨进程通信提供了稳定的进程状态管理框架。

构造函数

// 构造函数参数为 Binder 驱动设备路径(如 "/dev/binder")
ProcessState::ProcessState(const char* driver)
    : mDriverName(String8(driver)),  // [1] 存储驱动设备名称
      mDriverFD(-1),                 // [2] 初始化驱动文件描述符为无效值
      mVMStart(MAP_FAILED),          // [3] 内存映射起始地址初始化失败
      mThreadCountLock(PTHREAD_MUTEX_INITIALIZER),  // [4] 线程计数互斥锁初始化
      mThreadCountDecrement(PTHREAD_COND_INITIALIZER),  // [5] 条件变量初始化
      mMaxThreads(DEFAULT_MAX_BINDER_THREADS),  // [6] 设置 Binder 线程池最大线程数(默认15)
      ...  // 其他成员变量初始化略
{
    String8 error;
    unique_fd opened = open_driver(driver, &error);  // [7] 核心步骤:打开 Binder 驱动

    if (opened.ok()) {  // [8] 驱动打开成功
        // [9] 内存映射:分配内核缓冲区(零拷贝核心实现)
        mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, 
                        MAP_PRIVATE | MAP_NORESERVE, opened.get(), 0);
        if (mVMStart == MAP_FAILED) {  // [10] 映射失败处理
            ALOGE("Using %s failed: unable to mmap transaction memory.", driver);
            opened.reset();  // 关闭驱动文件
            mDriverName.clear();  // 清空设备名
        }
    }

#ifdef __ANDROID__  // [11] Android 环境下的致命错误检查
    LOG_ALWAYS_FATAL_IF(!opened.ok(),
        "Binder driver '%s' could not be opened. Error: %s. Terminating.",
        error.c_str(), driver);
#endif

    if (opened.ok()) {  // [12] 最终初始化成功
        mDriverFD = opened.release();  // [13] 转移文件描述符所有权
    }
}

一、关键逻辑解析​​

  • ​​驱动设备打开([7])​​
    open_driver() 通过系统调用打开 /dev/binder 设备,返回文件描述符。此步骤对应 Binder 驱动的 binder_init() 初始化流程,驱动会创建 binder_proc 结构体记录进程信息。
    ​​驱动检查​​:若设备不可用(如权限不足),Android 环境会触发致命错误终止进程,确保 Binder 机制可靠性。
  • ​​内存映射([9])​​
    ​​作用​​:通过 mmap 在内核空间分配 ​​BINDER_VM_SIZE​​(通常为 1MB)的共享内存,实现用户态与内核态的零拷贝通信。
    ​​参数解析​​:
    PROT_READ:用户空间仅需读权限,写操作由内核完成。
    MAP_PRIVATE:映射私有副本,避免多进程冲突。
    ​​Binder 驱动​​:通过此映射区域直接传递事务数据,省去传统 IPC 的数据拷贝开销。
  • ​​错误处理([10][11])​​
    ​​映射失败​​:若 mmap 失败(如内存不足),会关闭驱动并清空设备名,确保后续操作不会使用无效资源。
    ​​Android 强约束​​:在 Android 环境下,驱动打开失败直接终止进程(LOG_ALWAYS_FATAL_IF),因为 Binder 是系统核心组件。
  • ​​成员变量初始化​​
    ​​mDriverFD​​:保存驱动文件描述符,用于后续 ioctl 调用(如 BINDER_WRITE_READ 命令)。
    ​​mMaxThreads​​:控制 Binder 线程池大小,驱动根据此值管理线程创建与回收。
    ​​线程同步机制​​:通过互斥锁(mThreadCountLock)和条件变量(mThreadCountDecrement)管理线程池并发。

二、与 Binder 驱动的交互流程​​

  • ​​驱动初始化​​:内核启动时执行 binder_init(),注册 /dev/binder 设备并初始化调试节点(如 /sys/kernel/debug/binder)。
  • 进程绑定​​:用户态调用 open() 时,驱动创建 binder_proc 结构体,加入全局链表 binder_procs。
  • 内存管理​​:mmap 映射的内存区域由驱动管理,用于事务数据传输(如 binder_transaction_data 结构)。

三、​​总结​​

ProcessState 构造函数是 Android Binder 通信的起点,其通过打开驱动、内存映射等操作建立用户态与内核态的桥梁。理解其实现有助于深入掌握 Binder 的零拷贝机制与多线程模型。后续可通过分析 IPCThreadState 了解事务处理流程,或结合 ServiceManager 启动过程 研究服务的注册与发现机制。

open_driver

static unique_fd open_driver(const char* driver, String8* error) {
    // 步骤1:尝试以读写模式打开Binder驱动设备(如/dev/binder)
    auto fd = unique_fd(open(driver, O_RDWR | O_CLOEXEC));
    if (!fd.ok()) {  // 打开失败时记录错误信息
        error->appendFormat("%d (%s) Opening '%s' failed", errno, strerror(errno), driver);
        return {};
    }
    
    // 步骤2:检查驱动协议版本是否匹配
    int vers = 0;
    int result = ioctl(fd.get(), BINDER_VERSION, &vers);
    if (result == -1) {  // ioctl失败处理
        error->appendFormat("%d (%s) Binder ioctl to obtain version failed", errno, strerror(errno));
        return {};
    }
    if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {  // 版本不匹配处理
        error->appendFormat("Binder driver protocol(%d) does not match user space protocol(%d)! ioctl() return value: %d",
                            vers, BINDER_CURRENT_PROTOCOL_VERSION, result);
        return {};
    }

    // 步骤3:设置Binder线程池最大线程数(默认15)
    size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
    result = ioctl(fd.get(), BINDER_SET_MAX_THREADS, &maxThreads);
    if (result == -1) {  // 设置失败仅记录日志,不终止流程
        ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
    }

    // 步骤4:启用单向调用滥用检测(Android高版本特性)
    uint32_t enable = DEFAULT_ENABLE_ONEWAY_SPAM_DETECTION;
    result = ioctl(fd.get(), BINDER_ENABLE_ONEWAY_SPAM_DETECTION, &enable);
    if (result == -1) {  // 启用失败时按需记录日志
        ALOGE_IF(ProcessState::isDriverFeatureEnabled(
                     ProcessState::DriverFeature::ONEWAY_SPAM_DETECTION),
                 "Binder ioctl to enable oneway spam detection failed: %s", strerror(errno));
    }

    return fd;  // 返回已配置的驱动文件描述符
}

一、关键逻辑解析​​

  1. 驱动设备打开(open())​​
  • 作用​​:通过系统调用 open() 打开 Binder 设备文件(如 /dev/binder),返回文件描述符。
  • 驱动交互​​:触发内核中 binder_open() 函数,为进程创建 binder_proc 结构体,记录进程上下文信息。
  • 错误处理​​:若设备不存在或权限不足,记录错误并返回空文件描述符。
  1. 协议版本验证(BINDER_VERSION)​​
  • 必要性​​:确保用户空间与内核驱动的协议兼容性,避免因版本差异导致通信异常。
  • 实现机制​​:通过 ioctl 发送 BINDER_VERSION 命令,内核返回当前协议版本号。若版本不匹配,进程无法继续使用 Binder。
  1. 线程池配置(BINDER_SET_MAX_THREADS)​​
  • 默认值​​:DEFAULT_MAX_BINDER_THREADS 通常为 15,限制进程可创建的 Binder 线程数量。
  • 内核交互​​:驱动将用户空间传入的 maxThreads 值写入 binder_proc->max_threads,用于后续线程调度。
  • 容错处理​​:即使设置失败(如驱动不支持),进程仍可继续运行,但可能导致线程池容量不足。
  1. 单向调用防护(BINDER_ENABLE_ONEWAY_SPAM_DETECTION)​​
  • 功能背景​​:防止恶意进程通过单向调用(oneway)耗尽服务端资源,Android 12+ 引入的防护机制。
  • 实现逻辑​​:驱动监控单向调用的频率,超过阈值时触发限制策略(如丢弃请求或记录日志)。

二、​​与 Binder 驱动的交互流程​​

  1. ​​设备初始化​​:用户空间调用 open() 后,内核通过 binder_open() 创建 binder_proc 结构体,并加入全局链表 binder_procs。
  2. ​​版本协商​​:BINDER_VERSION 命令通过 binder_ioctl() 处理,直接返回内核协议版本。
  3. ​​线程池管理​​:BINDER_SET_MAX_THREADS 命令将用户空间参数拷贝至内核的 binder_proc->max_threads。
  4. ​​安全增强​​:BINDER_ENABLE_ONEWAY_SPAM_DETECTION 启用后,驱动在事务处理中增加频率检测逻辑。

三、错误处理策略​​

  1. ​​驱动打开失败​​:直接终止进程(Android 环境下)或记录错误(非 Android 环境)。
  2. ​​版本不匹配​​:视为致命错误,终止进程以避免通信异常。
  3. ​​线程配置失败​​:仅记录日志,不影响后续操作(但可能导致性能问题)。

四、​​总结​​

open_driver 是 Binder 通信初始化的核心函数,通过四个关键步骤确保驱动可用性、协议兼容性及资源可控性。其实现紧密结合 Binder 驱动机制,体现了 Android IPC 的高效性与安全性设计。后续可通过分析 mmap 和 IPCThreadState 进一步理解事务传输与线程调度机制。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值