Skip to content

Binder调用源码地图

沿服务发现和一次同步事务,追踪 Java、JNI、libbinder、Binder 驱动与服务线程之间的真实调用边界。

基于android-17.0.0_r1
AndroidBinderIPC源码阅读

Binder调用源码地图 ​

“Binder 是 Android 的 IPC 机制”只能作为名词解释,不能作为源码阅读路线。真正需要回答的问题是:客户端拿到的 IBinder 从哪里来,一次 transact() 如何变成驱动命令,服务进程的哪个线程收到它,reply 又怎样回到原调用线程。

本文面向已经掌握 Java/C++ 方法调用、JNI 基本概念、Linux 文件描述符和 AIDL 接口形状的读者。文章选择 ServiceManager.getService("activity") 作为服务发现入口,再选择一个同步 Binder 事务走通 Java、JNI、libbinder、内核驱动和服务端分发;不展开 oneway 队列、死亡通知、完整 Parcel 类型系统、线程池上限和 SELinux 策略,它们分别由后续文章负责。

读完后,读者应能:

  • 区分本地 Binder、远程 BinderProxy、native BpBinder 和内核 binder_ref;
  • 从 BinderProxy.transact() 追到 BINDER_WRITE_READ 和 BC_TRANSACTION;
  • 从 BR_TRANSACTION 找回服务端 BBinder/Java Binder.onTransact(),再解释同步 reply 的返回路径;
  • 根据 DEAD_OBJECT、BR_FAILED_REPLY、服务未找到和服务线程未注册等现象选择源码入口。

1. 问题边界 ​

Binder 文章常把“拿服务”和“调用服务”混为一条大图。它们在源码里是两个相邻但不同的入口:

  1. ServiceManager.getService(name) 先通过 context manager 查询名字到 Binder 引用的映射。
  2. 得到 IBinder 后,具体 AIDL 方法才调用 transact(code, data, reply, flags)。

服务发现的 owner 是 ServiceManager;一次业务事务的 owner 是客户端 Binder 对象、驱动事务和服务端 Binder 对象。

位置对象主要状态不能替代
客户端 JavaBinderProxynative mObject、handle、死亡状态服务端 Java Binder
客户端 nativeBpBinderhandle、mAlive、引用与事务入口内核 binder_ref
服务端 native/JavaBBinder/JavaBBinderExt本地对象、cookie、onTransact客户端代理

handle 是客户端进程中的描述符,不能直接当成服务端对象地址;服务端的 binder_node 才保存本地对象指针和 cookie。内核负责在两者之间建立引用关系。

2. 服务发现 ​

源码文件:frameworks/base/core/java/android/os/ServiceManager.java

相关函数:getIServiceManager()、getService()、rawGetService()

java
private static IServiceManager getIServiceManager() {
    if (sServiceManager != null) {
        return sServiceManager;
    }
    sServiceManager = ServiceManagerNative
            .asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
    return sServiceManager;
}

public static IBinder getService(String name) {
    try {
        IBinder service = sCache.get(name);
        if (service != null) {
            return service;
        } else {
            return Binder.allowBlocking(rawGetService(name));
        }
    } catch (RemoteException e) {
        Log.e(TAG, "error in getService", e);
    }
    return null;
}

private static IBinder rawGetService(String name) throws RemoteException {
    return getIServiceManager().getService2(name).getServiceWithMetadata().service;
}

首次查询先获得 context object,再把它解释为 IServiceManager 接口;目标服务查询是另一次 Binder 调用。sCache 命中时不会再次跨进程查询,这也是排查“第一次慢、后续快”时必须先看缓存分支的原因。

源码文件:frameworks/base/core/java/com/android/internal/os/BinderInternal.java

java
public static final native IBinder getContextObject();

源码文件:frameworks/base/core/jni/android_util_Binder.cpp

相关函数:android_os_BinderInternal_getContextObject()

cpp
static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
    return javaObjectForIBinder(env, b);
}

源码文件:frameworks/native/libs/binder/ProcessState.cpp

相关函数:getContextObject()、getStrongProxyForHandle()

cpp
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
    sp<IBinder> context = getStrongProxyForHandle(0);
    if (context) {
        internal::Stability::markCompilationUnit(context.get());
    } else {
        ALOGW("Not able to get context object on %s.", mDriverName.c_str());
    }
    return context;
}

handle 0 是 context manager 的特殊引用,不是所有服务的 handle。javaObjectForIBinder() 决定返回 Java BinderProxy 还是已有本地 Java 对象,后续 Java 接口调用才会落到正确的代理类型。

3. 代理形成 ​

源码文件:frameworks/base/core/java/android/os/BinderProxy.java

相关函数:transact()、transactNative()

java
public boolean transact(int code, Parcel data, Parcel reply, int flags)
        throws RemoteException {
    Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
    boolean warnOnBlocking = mWarnOnBlocking;
    if (warnOnBlocking && ((flags & FLAG_ONEWAY) == 0)
            && Binder.sWarnOnBlockingOnCurrentThread.get()) {
        mWarnOnBlocking = false;
        warnOnBlocking = false;
    }
    final boolean result = transactNative(code, data, reply, flags);
    return result;
}

public native boolean transactNative(int code, Parcel data, Parcel reply, int flags);

Java 层先检查 Parcel 大小,处理阻塞告警、事务监听器、AppOps 和 trace,再进入 JNI。上面的 片段只保留与调用方向有关的分支。transact() 返回 true 不等于业务方法返回 true;同步 调用的返回数据仍由 reply Parcel 承载。

源码文件:frameworks/base/core/jni/android_util_Binder.cpp

相关函数:android_os_BinderProxy_transact()

cpp
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
        jint code, jobject dataObj, jobject replyObj, jint flags)
{
    Parcel* data = parcelForJavaObject(env, dataObj);
    if (data == NULL) return JNI_FALSE;
    Parcel* reply = parcelForJavaObject(env, replyObj);
    if (reply == NULL && replyObj != NULL) return JNI_FALSE;

    IBinder* target = getBPNativeData(env, obj)->mObject.get();
    if (target == NULL) {
        jniThrowException(env, "java/lang/IllegalStateException",
                "Binder has been finalized!");
        return JNI_FALSE;
    }

    status_t err = target->transact(code, *data, reply, flags);
    if (err == NO_ERROR) return JNI_TRUE;
    signalExceptionForError(env, err);
    return JNI_FALSE;
}

这里的 target 是 native BpBinder,不是 Java BinderProxy 自身。JNI 只负责把 Java Parcel 和对象字段转换成 native 对象,并将 status_t 映射成 Java 层结果或异常。

源码文件:frameworks/native/libs/binder/BpBinder.cpp

相关函数:BpBinder::transact()

cpp
status_t BpBinder::transact(uint32_t code, const Parcel& data,
        Parcel* reply, uint32_t flags) {
    if (mAlive) {
        status_t status;
        if (isRpcBinder()) {
            status = rpcSession()->transact(
                    sp<IBinder>::fromExisting(this), code, data, reply, flags);
        } else {
            status = IPCThreadState::self()->transact(
                    binderHandle(), code, data, reply, flags);
        }
        if (status == DEAD_OBJECT) mAlive = 0;
        return status;
    }
    return DEAD_OBJECT;
}

Android 17 的 BpBinder 同时保留 kernel Binder 和 RPC 分支;本文只继续 kernel Binder 分支。mAlive 是代理侧的快速状态,不是内核引用的全部生命周期。

4. 事务封装 ​

源码文件:frameworks/native/libs/binder/IPCThreadState.cpp

相关函数:transact()、writeTransactionData()

cpp
status_t IPCThreadState::transact(int32_t handle, uint32_t code,
        const Parcel& data, Parcel* reply, uint32_t flags) {
    flags |= TF_ACCEPT_FDS;
    status_t err = writeTransactionData(
            BC_TRANSACTION, flags, handle, code, data, nullptr);
    if (err != NO_ERROR) {
        if (reply) reply->setError(err);
        return (mLastError = err);
    }

    if ((flags & TF_ONE_WAY) == 0) {
        if (reply) {
            err = waitForResponse(reply);
        } else {
            Parcel fakeReply;
            err = waitForResponse(&fakeReply);
        }
    } else {
        err = waitForResponse(nullptr, nullptr);
    }
    return err;
}

同步和 oneway 的分叉在这里出现:同步调用发送 BC_TRANSACTION 后等待 reply;oneway 不需要业务 reply,但仍会通过驱动处理完成或失败命令。

源码文件:frameworks/native/libs/binder/IPCThreadState.cpp

相关函数:writeTransactionData()

cpp
status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
        int32_t handle, uint32_t code, const Parcel& data,
        status_t* statusBuffer) {
    binder_transaction_data tr;
    tr.target.ptr = 0;
    tr.target.handle = handle;
    tr.code = code;
    tr.flags = binderFlags;
    tr.cookie = 0;
    tr.sender_pid = 0;
    tr.sender_euid = 0;
    tr.data_size = data.ipcDataSize();
    tr.data.ptr.buffer = data.ipcData();
    tr.offsets_size = data.ipcObjectsCount() * sizeof(binder_size_t);
    tr.data.ptr.offsets = data.ipcObjects();

    mOut.writeInt32(cmd);
    mOut.write(&tr, sizeof(tr));
    return NO_ERROR;
}

mOut 是当前 Binder 线程准备交给驱动的命令缓冲区;binder_transaction_data 携带目标 handle、接口 code、flags、数据地址和对象偏移数组。

源码文件:kernel/common/include/uapi/linux/android/binder.h

c
struct binder_write_read {
    binder_size_t write_size;
    binder_size_t write_consumed;
    binder_uintptr_t write_buffer;
    binder_size_t read_size;
    binder_size_t read_consumed;
    binder_uintptr_t read_buffer;
};

struct binder_transaction_data {
    union { binder_uintptr_t ptr; binder_uint32_t handle; } target;
    binder_uintptr_t cookie;
    binder_uint32_t code;
    binder_uint32_t flags;
    pid_t sender_pid;
    uid_t sender_euid;
    binder_size_t data_size;
    binder_size_t offsets_size;
    union {
        struct { binder_uintptr_t buffer; binder_uintptr_t offsets; } ptr;
        uint8_t buf[8];
    } data;
};

5. 驱动入队 ​

源码文件:kernel/common/drivers/android/binder.c

相关函数:binder_ioctl()、binder_ioctl_write_read()

c
static long binder_ioctl(struct file *filp, unsigned int cmd,
        unsigned long arg) {
    int ret;
    struct binder_proc *proc = filp->private_data;
    struct binder_thread *thread;

    thread = binder_get_thread(proc);
    if (thread == NULL) {
        ret = -ENOMEM;
        goto err;
    }
    switch (cmd) {
    case BINDER_WRITE_READ:
        ret = binder_ioctl_write_read(filp, arg, thread);
        if (ret)
            goto err;
        break;
    }
err:
    return ret;
}

BINDER_WRITE_READ 同时承载用户态写命令和读回命令。驱动先为调用进程找到 binder_proc,再为当前线程找到 binder_thread;同一个文件描述符不等于一个 Binder 线程。

源码文件:kernel/common/drivers/android/binder.c

相关函数:binder_thread_write()、binder_transaction()

c
case BC_TRANSACTION:
case BC_REPLY: {
    struct binder_transaction_data tr;

    if (copy_from_user(&tr, ptr, sizeof(tr)))
        return -EFAULT;
    ptr += sizeof(tr);
    binder_transaction(proc, thread, &tr, cmd == BC_REPLY, 0);
    break;
}

驱动把 BC_TRANSACTION 和 BC_REPLY 都送入 binder_transaction(),区别由 reply 参数和当前线程的事务栈决定。一次同步调用在客户端先创建事务;服务端回复时,驱动通过服务线程的 transaction_stack 找回等待中的父事务。

源码文件:kernel/common/drivers/android/binder.c

相关函数:binder_transaction()

c
static void binder_transaction(struct binder_proc *proc,
        struct binder_thread *thread, struct binder_transaction_data *tr,
        int reply, binder_size_t extra_buffers_size) {
    struct binder_transaction *t;
    struct binder_proc *target_proc = NULL;
    struct binder_thread *target_thread = NULL;
    struct binder_node *target_node = NULL;

    t = kzalloc(sizeof(*t), GFP_KERNEL);
    if (!t) {
        return;
    }
    // 根据 target.handle / target.ptr 找目标进程、线程和 node
    // 为目标进程分配 binder_buffer 并转换对象
}

对于远程代理发出的调用,tr.target.handle 在客户端引用树中解析为目标 binder_node;目标进程、目标线程和事务 buffer 都由驱动决定。用户态 BpBinder 不直接知道服务线程的 TID,也不能绕过驱动把 C++ 指针交给另一进程。

源码文件:kernel/common/drivers/android/binder.c

c
t->buffer = binder_alloc_new_buf(&target_proc->alloc,
        tr->data_size, tr->offsets_size, extra_buffers_size,
        !reply && (t->flags & TF_ONE_WAY));
if (IS_ERR(t->buffer)) {
    return_error = PTR_ERR(t->buffer) == -ESRCH
            ? BR_DEAD_REPLY : BR_FAILED_REPLY;
    goto err_binder_alloc_buf_failed;
}
t->buffer->debug_id = t->debug_id;
t->buffer->transaction = t;
t->buffer->target_node = target_node;

buffer 属于目标进程的 binder_alloc,不是发送方 Parcel 的永久存储。内存不足、目标地址空间已清除或对象偏移非法都会在这里改变事务结果。

6. 服务线程 ​

源码文件:kernel/common/drivers/android/binder.c

相关函数:binder_thread_read()、binder_wait_for_work()

c
static int binder_thread_read(struct binder_proc *proc,
        struct binder_thread *thread, binder_uintptr_t binder_buffer,
        size_t size, binder_size_t *consumed, int non_block) {
    int wait_for_proc_work;

    binder_inner_proc_lock(proc);
    wait_for_proc_work = binder_available_for_proc_work_ilocked(thread);
    binder_inner_proc_unlock(proc);
    thread->looper |= BINDER_LOOPER_STATE_WAITING;
    if (non_block) {
        if (!binder_has_work(thread, wait_for_proc_work)) {
            return -EAGAIN;
        }
    } else {
        binder_wait_for_work(thread, wait_for_proc_work);
    }
    // 从 thread->todo 或 proc->todo 生成 BR_TRANSACTION/BR_REPLY
}

服务线程主动通过 BINDER_WRITE_READ 的 read 部分等待,驱动将可执行事务编码成 BR_TRANSACTION 写入该线程的用户缓冲区;用户态再读取并调用 IPCThreadState::executeCommand()。

源码文件:kernel/common/drivers/android/binder.c

c
if (t->buffer->target_node) {
    struct binder_node *target_node = t->buffer->target_node;
    trd->target.ptr = target_node->ptr;
    trd->cookie = target_node->cookie;
    cmd = BR_TRANSACTION;
} else {
    trd->target.ptr = 0;
    trd->cookie = 0;
    cmd = BR_REPLY;
}
trd->code = t->code;
trd->flags = t->flags;
trd->data_size = t->buffer->data_size;
trd->offsets_size = t->buffer->offsets_size;

target.ptr/cookie 让服务端 native 层找回本地对象;没有 target_node 时,驱动把它编码成 BR_REPLY。同步事务会压入服务线程的 transaction_stack,oneway 或 reply 则有不同的释放时机。

源码文件:frameworks/native/libs/binder/IPCThreadState.cpp

相关函数:executeCommand()

cpp
case BR_TRANSACTION_SEC_CTX:
case BR_TRANSACTION: {
    binder_transaction_data_secctx tr_secctx;
    binder_transaction_data& tr = tr_secctx.transaction_data;
    result = mIn.read(&tr, sizeof(tr));

    Parcel buffer;
    buffer.ipcSetDataReference(
            reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
            tr.data_size,
            reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
            tr.offsets_size / sizeof(binder_size_t), freeBuffer);

    if (tr.target.ptr) {
        BBinder* binder = reinterpret_cast<BBinder*>(tr.cookie);
        error = doTransactBinder(binder, tr.code, buffer, &reply, tr.flags);
    } else {
        error = doTransactBinder(the_context_object.get(),
                tr.code, buffer, &reply, tr.flags);
    }
}

服务端分发使用 cookie 找到 BBinder,而不是重新通过 handle 查询。

7. Java落点 ​

源码文件:frameworks/base/core/jni/android_util_Binder.cpp

相关类型:JavaBBinderExt、JavaBBinderHolder

cpp
class JavaBBinderExt : public android::internal::JavaBBinderBase {
public:
    JavaBBinderExt(JNIEnv* env, jobject object)
            : JavaBBinderBase(env, object) {}

    status_t onTransact(uint32_t code, const Parcel& data,
            Parcel* reply, uint32_t flags = 0) override {
        JNIEnv* env = javavm_to_jnienv(mVM);
        IPCThreadState* thread_state = IPCThreadState::self();
        const int32_t strict_policy_before = thread_state->getStrictModePolicy();
        jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
                code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);
        if (env->ExceptionCheck()) {
            res = JNI_FALSE;
        }
        if (thread_state->getStrictModePolicy() != strict_policy_before) {
            set_dalvik_blockguard_policy(env, strict_policy_before);
        }
        return res != JNI_FALSE ? NO_ERROR : UNKNOWN_TRANSACTION;
    }
};

Java Binder 对象通过 JavaBBinderExt 变成 native BBinder;驱动保存的是 native node 的 ptr/cookie,不是 Java 对象地址。

源码文件:frameworks/base/core/java/android/os/Binder.java

相关函数:execTransact()、execTransactInternal()、onTransact()

java
private boolean execTransact(int code, long dataObj, long replyObj, int flags) {
    Parcel data = Parcel.obtain(dataObj);
    Parcel reply = Parcel.obtain(replyObj);
    try {
        final int callingUid = Binder.getCallingUid();
        return execTransactInternal(code, data, reply, flags, callingUid);
    } finally {
        reply.recycle();
        data.recycle();
    }
}

private boolean execTransactInternal(int code, Parcel data, Parcel reply,
        int flags, int callingUid) {
    return onTransact(code, data, reply, flags);
}

生成的 AIDL Stub 通常覆写 onTransact(),先校验接口 token,再读 Parcel、调用实现、写入 reply。Binder 基类负责把 native buffer 变成 Java Parcel 并在 finally 中回收。

8. 回复收束 ​

源码文件:frameworks/native/libs/binder/IPCThreadState.cpp

相关函数:sendReply()、waitForResponse()

cpp
status_t IPCThreadState::sendReply(const Parcel& reply, uint32_t flags) {
    status_t statusBuffer;
    status_t err = writeTransactionData(
            BC_REPLY, flags, -1, 0, reply, &statusBuffer);
    if (err < NO_ERROR) return err;
    return waitForResponse(nullptr, nullptr);
}

服务线程把 reply 写成 BC_REPLY,驱动依据当前事务栈找到客户端等待的线程,并为客户端生成 BR_REPLY。

源码文件:frameworks/native/libs/binder/IPCThreadState.cpp

cpp
status_t IPCThreadState::waitForResponse(Parcel* reply,
        status_t* acquireResult) {
    while (true) {
        status_t err = talkWithDriver();
        if (err < NO_ERROR) return err;
        if (mIn.dataAvail() == 0) continue;

        uint32_t cmd = static_cast<uint32_t>(mIn.readInt32());
        switch (cmd) {
        case BR_TRANSACTION_COMPLETE:
            if (!reply && !acquireResult) return NO_ERROR;
            break;
        case BR_REPLY:
            // 读取 binder_transaction_data,填充 reply
            goto finish;
        case BR_DEAD_REPLY:
            return DEAD_OBJECT;
        }
    }
finish:
    return NO_ERROR;
}

BR_TRANSACTION_COMPLETE 只说明驱动接受了发送命令;同步业务结果要等 BR_REPLY。

源码文件:frameworks/native/libs/binder/IPCThreadState.cpp

相关函数:talkWithDriver()

cpp
binder_write_read bwr;
const bool needRead = mIn.dataPosition() >= mIn.dataSize();
const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;

bwr.write_size = outAvail;
bwr.write_buffer = reinterpret_cast<uintptr_t>(mOut.data());
bwr.read_size = doReceive && needRead ? mIn.dataCapacity() : 0;
bwr.read_buffer = doReceive && needRead
        ? reinterpret_cast<uintptr_t>(mIn.data()) : 0;

status_t err = ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr);

Binder 的“写请求、阻塞等 reply”不是两个必然分离的系统调用,而是通过一个 binder_write_read 结构把待写命令和待读数据同时交给驱动。

9. 失败变化 ​

服务不存在 ​

ServiceManager.getService() 缓存未命中时调用 rawGetService();服务名不存在可能返回 null,调用方随后可能抛出自己的 ServiceNotFoundException。这条路径尚未进入 BinderProxy.transact(),不应从 transaction log 反查。

代理已死亡 ​

BpBinder::transact() 在 mAlive == false 时直接返回 DEAD_OBJECT;即使此前 handle 曾经对应一个服务,代理也不会因服务重启自动重新绑定。Java 层通常把它映射成 RemoteException 或其子类,恢复策略属于 ServiceManager/调用方,而不是 Binder 驱动自动完成。

buffer失败 ​

驱动在 binder_alloc_new_buf() 失败时区分目标已死亡、空间不足和内存分配失败,分别生成 BR_DEAD_REPLY 或 BR_FAILED_REPLY 等结果。此时服务端不会执行 onTransact();如果只看客户端“方法没有返回”,必须把失败位置前移到驱动 buffer 分配和对象转换。

服务线程退出 ​

服务线程需要通过 joinThreadPool() 或等价路径持续读驱动;如果没有线程读取,事务可以已经进入目标进程 todo,但不会进入 executeCommand()。这与服务对象不存在不同:前者可能有 node 和进程,但缺少活跃消费者。

分支请求方等待服务端 reply适合的定位问题
同步waitForResponse(reply)BC_REPLY/BR_REPLY方法结果、服务阻塞、reply 失败
oneway不等待业务 reply不发送业务 reply异步排队、服务线程消费、冻结状态

10. 测试输入 ​

源码文件:frameworks/native/libs/binder/tests/binderLibTest.cpp

相关测试:BinderLibTest.NopTransaction、BinderLibTest.NopTransactionOneway、BinderLibTest.AddServer

cpp
TEST_F(BinderLibTest, NopTransaction) {
    Parcel data, reply;
    EXPECT_THAT(m_server->transact(
            BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply),
            StatusEq(NO_ERROR));
}

TEST_F(BinderLibTest, NopTransactionOneway) {
    Parcel data, reply;
    EXPECT_THAT(m_server->transact(
            BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply, TF_ONE_WAY),
            StatusEq(NO_ERROR));
}

测试先启动独立 server,再获取 Binder 引用;两条测试都构造 data/reply Parcel,分别用普通 flags 和 TF_ONE_WAY 调用并断言 NO_ERROR。它能说明两种事务入口的基本往返,不能证明 具体服务的权限、延迟、线程数或所有 Parcel 对象转换。

源码文件:frameworks/base/core/tests/coretests/src/android/os/BinderProxyTest.java

相关测试:BinderProxyTest.testNoListener、BinderProxyTest.testListener、 BinderProxyTest.testSessionPropagated

这些测试通过 ActivityManager 的真实 Binder 调用检查代理监听器的开始/结束计数和 session 传递。它们能说明 Java 代理的观测边界,不能替代 native 驱动往返测试。

11. 阅读边界 ​

本文主线证明的是:

  • context manager handle 0 如何变成 Java 服务管理代理;
  • Java BinderProxy 如何经 JNI 找到 native BpBinder;
  • BpBinder → IPCThreadState → BINDER_WRITE_READ → binder_transaction 的同步请求路径;
  • 驱动如何把 BR_TRANSACTION 交给服务线程,再由 BBinder/Java Binder 执行;
  • BC_REPLY → BR_REPLY 如何回到原调用线程,以及失败在哪些边界提前终止。

以下问题留给后续文章:

  • binder_open、binder_mmap 和 allocator 页管理;
  • binder_node、binder_ref 和对象引用计数;
  • 完整 Parcel 对象转换和 FD 传递;
  • ServiceManager 注册、死亡通知和 lazy service;
  • 线程池、嵌套调用和事务耗尽。

作为前置复习,可以回看 消息机制总览 理解服务线程收到事务后如何把工作转交给 Handler;下一篇 Binder 文章将从驱动打开和 binder_proc 创建继续向下展开。

12. 复查任务 ​

选一个真实系统服务,例如 activity,完成下面的只读任务:

  1. 从 ServiceManager.getService("activity") 标出缓存分支、context object 和 getService2()。
  2. 在 BinderProxy.transact() 标出 Java → JNI → BpBinder 的三个对象转换。
  3. 在 IPCThreadState::writeTransactionData() 记录 handle、code、flags、data size 和 offsets。
  4. 在驱动 binder_transaction() 找到目标进程、目标 node 和 buffer 分配。
  5. 在 binder_thread_read() 和 executeCommand(BR_TRANSACTION) 找到服务线程的消费者。
  6. 在 waitForResponse() 区分 BR_TRANSACTION_COMPLETE、BR_REPLY 和 BR_DEAD_REPLY。

如果这条路径中任何一步只能说“Binder 把数据传过去了”,就回到该步骤的 owner 和状态字段:Binder 的难点不在组件数量,而在同一个事务状态先后由 Java 对象、native 线程、内核 proc/thread、目标 buffer 和服务对象分别持有。

13. 地图使用法 ​

本文是导航文章,不承担每个子系统的完整机制证明。阅读时先用 ServiceManager.getService 确认名称到 handle 的边界,再用 BpBinder::transact 进入一次具体事务;当问题转向 allocator、死亡通知、线程池或 SELinux 时,应停止沿本图扩展,转入对应专题。这样可以避免把一张跨层地图误当成所有实现细节的替代品。

源码块中的 handle、code、flags 和 data size 是跨层追踪的四个锚点:调用方写入它们,驱动据此选择 node/thread/buffer,服务端 Stub 消费它们,reply 再沿 transaction stack 返回。读者可在每层记录这四个值,验证自己没有在对象层级之间跳步。