AOSP15 Binder专题之应用程序app的Binder启动详细分析

在 AOSP 15 中,应用程序进程的 Binder 启动是一个从 Native 层驱动初始化到 Java 层框架绑定的闭环过程。这个过程保证了 App 既能作为"客户端"调用系统服务,也能作为"服务端"接收系统的指令(如生命周期回调)。

以下是 Binder 启动的详细代码调用流程分析。

一、 Native 层的 Binder 通道建立

App 进程由 Zygote 进程 fork 出来。在进程创建后,首要任务是初始化 ProcessState,这是 Binder 通信在 Native 层的单例管理者。

1. 关键代码路径追踪

第一步:Java 层的 Fork 动作

system_server 请求启动 App 时,Zygote 接收 socket 消息并进入 fork 流程。

  • 文件: frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
  • 函数: processOneCommand() -> Zygote.forkAndSpecialize()

Zygote.forkAndSpecialize 调用后,系统执行了真正的 Linux fork()。此时:

  1. **父进程(Zygote)**继续监听 Socket。
  2. **子进程(App)**开始执行初始化逻辑。

第二步:进入子进程初始化

子进程 fork 出来后,会执行 handleChildProc,最终调用到 ZygoteInit.zygoteInit

  • 文件: frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

第三步:JNI 跳转 (从 Java 到 Native)

ZygoteInit.nativeZygoteInit() 是一个 native 方法,它映射到了 AndroidRuntime.cpp 中。

  • 文件: frameworks/base/core/jni/AndroidRuntime.cpp

    注意: gCurRuntime 是一个全局指针,它的实际指向是在 app_main.cpp 的 main 函数中定义的 AppRuntime 实例。

第四步:执行目的地 AppRuntime::onZygoteInit

最后,逻辑回到了我们最熟悉的 app_main.cpp。

  • 文件: frameworks/base/cmds/app_process/app_main.cpp
c++ 复制代码
virtual void onZygoteInit()
{
    sp<ProcessState> proc = ProcessState::self();
    ALOGV("App process: starting thread pool.\n");
    proc->startThreadPool();
}

2. 初始化 ProcessState (核心)

在 ProcessState 的构造函数中,App 进程正式与 /dev/binder 驱动建立联系。

  • 源文件: frameworks/native/libs/binder/ProcessState.cpp
  • 关键动作:
  1. open: 调用 open("/dev/binder", ...) 打开驱动。
  2. mmap: 映射内存,AOSP 15 中默认大小依然遵循: <math xmlns="http://www.w3.org/1998/Math/MathML"> Binder Size = 1 MB − 8 KB \text{Binder Size} = 1\text{MB} - 8\text{KB} </math>Binder Size=1MB−8KB
  3. 设置最大线程数: 默认通过 ioctl 告知驱动,该进程支持的 Binder 线程池最大数量(默认为 15)。

二、onZygoteInit具体实现流程

  • 文件: frameworks/base/cmds/app_process/app_main.cpp
c++ 复制代码
virtual void onZygoteInit()
{
    sp<ProcessState> proc = ProcessState::self();
    ALOGV("App process: starting thread pool.\n");
    proc->startThreadPool();
}

1、self()

c++ 复制代码
sp<ProcessState> ProcessState::self()
{
    return init(kDefaultDriver, false /*requireDefault*/);
}

2、init()

c++ 复制代码
sp<ProcessState> ProcessState::init(const char* driver, bool requireDefault) {
    if (driver == nullptr) {
        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, [&](){
        if (access(driver, R_OK) == -1) {
            ALOGE("Binder driver %s is unavailable. Using /dev/binder instead.", driver);
            driver = "/dev/binder";
        }
        // ....
        std::lock_guard<std::mutex> l(gProcessMutex);
        // sp<T>::make 相当于安全地执行了 new ProcessState(driver)
        gProcess = sp<ProcessState>::make(driver);
    });

    // ...
    return gProcess;
}

3、在构造函数中:执行 open("/dev/binder") 和 mmap。

c++ 复制代码
ProcessState::ProcessState(const char* driver)
      : mDriverName(String8(driver)),
        mDriverFD(-1),
        mVMStart(MAP_FAILED),
        mExecutingThreadsCount(0),
        mMaxThreads(DEFAULT_MAX_BINDER_THREADS),
        mCurrentThreads(0),
        mKernelStartedThreads(0),
        mStarvationStartTime(never()),
        mForked(false),
        mThreadPoolStarted(false),
        mThreadPoolSeq(1),
        mCallRestriction(CallRestriction::NONE) {
    String8 error;
    // 打开驱动
    unique_fd opened = open_driver(driver, &error);

    if (opened.ok()) {
        // mmap 申请内存
        mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, opened.get(), 0);
        if (mVMStart == MAP_FAILED) {
            // ...
            opened.reset();
            mDriverName.clear();
        }
    }

#ifdef __ANDROID__
    LOG_ALWAYS_FATAL_IF(!opened.ok(),
                        "Binder driver '%s' could not be opened. Error: %s. Terminating.",
                        driver, error.c_str());
#endif

    if (opened.ok()) {
        mDriverFD = opened.release();
    }
}

注意: #define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)

  • 旧版 (4KB Page):BINDER_VM_SIZE 是 <math xmlns="http://www.w3.org/1998/Math/MathML"> 1024 K B − 8 K B 1024KB - 8KB </math>1024KB−8KB。
  • AOSP 15 (16KB 支持):如果底层硬件使用 16KB 页面,BINDER_VM_SIZE 会自动适配为 <math xmlns="http://www.w3.org/1998/Math/MathML"> 1024 K B − 32 K B 1024KB - 32KB </math>1024KB−32KB。
  • 目的:确保映射区域的边界始终与系统的页面大小对齐(Page Aligned),否则 mmap 会直接失败,导致 App 崩溃

4、startThreadPool()

c++ 复制代码
void ProcessState::startThreadPool()
{
    std::unique_lock<std::mutex> _l(mLock);
    if (!mThreadPoolStarted) {
        if (mMaxThreads == 0) {
            // see also getThreadPoolMaxTotalThreadCount
            ALOGW("Extra binder thread started, but 0 threads requested. Do not use "
                  "*startThreadPool when zero threads are requested.");
        }
        mThreadPoolStarted = true;
        spawnPooledThread(true);
    }
}

5、spawnPooledThread(bool isMain)

c++ 复制代码
void ProcessState::spawnPooledThread(bool isMain)
{
    if (mThreadPoolStarted) {
        String8 name = makeBinderThreadName();
        //  sp<T>::make 相当于安全地执行了 new PoolThread()
        sp<Thread> t = sp<PoolThread>::make(isMain);
        t->run(name.c_str());
        mKernelStartedThreads++;
    }
}

6、启动了一个PoolThread线程

c++ 复制代码
class PoolThread : public Thread
{
public:
    explicit PoolThread(bool isMain)
        : mIsMain(isMain)
    {
    }

protected:
    virtual bool threadLoop()
    {
        IPCThreadState::self()->joinThreadPool(mIsMain);
        return false;
    }

    const bool mIsMain;
};

7、spawnPooledThread

c++ 复制代码
void ProcessState::spawnPooledThread(bool isMain)
{
    if (mThreadPoolStarted) {
        String8 name = makeBinderThreadName();
        //  sp<T>::make 相当于安全地执行了 new PoolThread()
        sp<Thread> t = sp<PoolThread>::make(isMain);
        t->run(name.c_str());
        mKernelStartedThreads++;
    }
}

6、启动了一个PoolThread线程

c++ 复制代码
IPCThreadState* IPCThreadState::self()
{
    // 单例
    if (gHaveTLS.load(std::memory_order_acquire)) {
restart:
        const pthread_key_t k = gTLS;
        // 尝试从当前线程的私有存储空间中根据 Key (gTLS) 取出对象
        IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
        if (st) return st;
        // 构造函数中,它会调用 pthread_setspecific 将自己存入 TLS
        return new IPCThreadState;
    }

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

    pthread_mutex_lock(&gTLSMutex);
    // 确保多线程环境下,Key 的创建对所有线程可见。
    if (!gHaveTLS.load(std::memory_order_relaxed)) {
        // 这是整个进程生命周期中只运行一次的代码。它向 Linux 系统申请一个全局唯一的 Key (gTLS)。
        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 nullptr;
        }
        gHaveTLS.store(true, std::memory_order_release);
    }
    pthread_mutex_unlock(&gTLSMutex);
    goto restart;
}

7、joinThreadPool

c++ 复制代码
void IPCThreadState::joinThreadPool(bool isMain)
{
    LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(),
                   getpid());
    mProcess->mCurrentThreads++;
    mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);

    mIsLooper = true;
    status_t result;
    do {
        processPendingDerefs();
        // 关键代码
        result = getAndExecuteCommand();

        if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) {
            LOG_ALWAYS_FATAL("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",
                  mProcess->mDriverFD, result);
        }
        if(result == TIMED_OUT && !isMain) {
            break;
        }
    } while (result != -ECONNREFUSED && result != -EBADF);

    LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%d\n",
        (void*)pthread_self(), getpid(), result);

    mOut.writeInt32(BC_EXIT_LOOPER);
    mIsLooper = false;
    talkWithDriver(false);
    size_t oldCount = mProcess->mCurrentThreads.fetch_sub(1);
}

总结

  • 1、打开binder驱动
  • 2、binder映射对应的内存
  • 3、启动binder线程
  • 4、获取IPCThread对象
  • 5、通知binder驱动已经进入循环

参考

千里马:https://blog.csdn.net/learnframework/article/details/118465159?spm=1001.2014.3001.5502

相关推荐
huwuhang3 分钟前
索尼PS3游戏合集【中文游戏】8.12T 1430个游戏+PS3模拟器
android·游戏·智能手机·游戏机·电视
Grackers2 小时前
Android Perfetto 系列 5:Android App 基于 Choreographer 的渲染流程
android
踩着两条虫2 小时前
AI驱动的Vue3应用开发平台深入探究(十):物料系统之内置组件库
android·前端·vue.js·人工智能·低代码·系统架构·rxjava
sam.li2 小时前
JADX MCP 原理与使用部署
android·逆向·jadx
冬奇Lab3 小时前
Android 15音频子系统(五):AudioPolicyService策略管理深度解析
android·音视频开发·源码阅读
亚历克斯神3 小时前
Flutter for OpenHarmony: Flutter 三方库 mutex 为鸿蒙异步任务提供可靠的临界资源互斥锁(并发安全基石)
android·数据库·安全·flutter·华为·harmonyos
dalancon5 小时前
SurfaceControl 的事务提交给 SurfaceFlinger,以及 SurfaceFlinger 如何将这些数据设置到对应 Layer 的完整流程
android
dalancon5 小时前
SurfaceFlinger Layer 到 HWC 通信流程详解
android
cccccc语言我来了5 小时前
Linux(9)操作系统
android·java·linux
yige455 小时前
【MySQL】MySQL内置函数--日期函数字符串函数数学函数其他相关函数
android·mysql·adb