Android FrameWork(二)—— Binder浅析(下)

Android FrameWork(二)—— Binder浅析(上)

经过上一篇博客的介绍,相信大家已经对于 binder 机制有了一定的了解,这篇博客将会解读 AMS 与 SM 通信的代码流程,篇幅会很长,请大家耐心看完!

(以下分析的是 Android 6.0 的源码)

SM 是怎么启动的?

AMS 在启动后会注册到 ServiceManager(之后简称为SM)中。那么 SM 是如何启动的?

SM 是由 init 进程通过解析 init.rc 文件而创建的,其所对应的可执行程序 servicemanager,
所对应的源文件是 service_manager.c,进程名为 servicemanager。

启动 SM 的入口函数是 service_manager.c 中的 main 方法。

int main(int argc, char **argv)
{
    struct binder_state *bs;
    // 打开binder驱动,映射 128K 大小的内存空间
    bs = binder_open(128*1024);
    ......
    // 把当前进程注册成为 SM
    if (binder_become_context_manager(bs))
    {
        ALOGE("cannot become context manager (%s)\n", strerror(errno));
        return -1;
    }
    ......
    // 进入 loop 无限循环,监听处理 AMS 端发来的请求
    binder_loop(bs, svcmgr_handler);
    return 0;
}
复制代码

我们先来看 binder_open 函数具体做了什么。

// frameworks/native/cmds/servicemanager/binder.c
struct binder_state *binder_open(size_t mapsize)
{
    struct binder_state *bs;
    struct binder_version vers;
    ......
    // 打开binder驱动,得到文件描述符,通过系统调用到 binder 驱动中的 binder_open 函数
    bs->fd = open("/dev/binder", O_RDWR);
    ......
    // 映射内存大小:128K
    bs->mapsize = mapsize;
    // 通过系统调用到 binder 驱动中的 binder_mmap 函数,
    // 在当前进程的用户空间和内核空间之间映射 128K 大小的内存空间
    bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
    ......
    return bs;
    ......
}
复制代码

我们接着来看 binder_become_context_manager 函数具体做了什么。

// frameworks/native/cmds/servicemanager/binder.c
int binder_become_context_manager(struct binder_state *bs)
{
    // 通过系统调用到 binder 驱动中的 binder_ioctl 函数,指令为 BINDER_SET_CONTEXT_MGR
    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}

// kernel/drivers/staging/android/binder.c
static long binder_ioctl(struct file *filp, 
                        unsigned int cmd, // cmd 就是我们传入的 BINDER_SET_CONTEXT_MGR
                        unsigned long arg
){
    ......
    switch (cmd)
    {
        ......
        case BINDER_SET_CONTEXT_MGR:
            ret = binder_ioctl_set_ctx_mgr(filp);
            ......
            break;
        ......
    }
    ......
    return ret;
}

static int binder_ioctl_set_ctx_mgr(struct file *filp)
{
    // 获取 binder 驱动的设备节点实体,可以通过 filp->private_data 获取
    struct binder_proc *proc = filp->private_data;
    ......
    // 保证只创建一次 binder_context_mgr_node,不为null就直接返回
    if (context->binder_context_mgr_node)
    {
        ......
        goto out;
    }
    ......
    // uid 是否有效,当前是无效的
    if (uid_valid(context->binder_context_mgr_uid))
    {
        if (!uid_eq(context->binder_context_mgr_uid, curr_euid))
        {
            ......
            goto out;
        }
    }
    else
    {
        // 设置当前线程的 euid 作为 SM 的 uid
        context->binder_context_mgr_uid = curr_euid;
    }
    // 创建 SM 在 binder 驱动中的 binder 节点实体
    context->binder_context_mgr_node = binder_new_node(proc, 0, 0);
    ......
out:
    return ret;
}

static struct binder_node *binder_new_node(struct binder_proc *proc, // binder 驱动的设备节点实体
					   binder_uintptr_t ptr,
					   binder_uintptr_t cookie
){
    struct rb_node **p = &proc->nodes.rb_node;
    struct rb_node *parent = NULL;
    struct binder_node *node;
    ......
    // 给新创建的 binder_node 分配内核空间的内存
    node = kzalloc(sizeof(*node), GFP_KERNEL);
    ......
    // 将新创建的 binder_node 添加到设备节点的 binder_node 红黑树中
    rb_link_node(&node->rb_node, parent, p);
    rb_insert_color(&node->rb_node, &proc->nodes);
    ......
    // 初始化新创建的 binder_node
    node->proc = proc;
    node->ptr = ptr;
    node->cookie = cookie;
    node->work.type = BINDER_WORK_NODE;
    INIT_LIST_HEAD(&node->work.entry);
    INIT_LIST_HEAD(&node->async_todo);
    ......
    return node;
}
复制代码

binder_become_context_manager 函数中主要是创建了 SM 在 binder 驱动中的节点实体。

我们接着来看 binder_loop 函数具体做了什么。

// frameworks/native/cmds/servicemanager/binder.c
void binder_loop(struct binder_state *bs, binder_handler func)
{
    int res;
    struct binder_write_read bwr;
    uint32_t readbuf[32];

    bwr.write_size = 0;
    bwr.write_consumed = 0;
    bwr.write_buffer = 0;

    readbuf[0] = BC_ENTER_LOOPER;
    // 发送指令 BC_ENTER_LOOPER 给 binder 驱动,
    // 给当前线程的 looper 添加标志 BINDER_LOOPER_STATE_ENTERED
    binder_write(bs, readbuf, sizeof(uint32_t));

    for (;;)
    {
        bwr.read_size = sizeof(readbuf);
        bwr.read_consumed = 0;
        bwr.read_buffer = (uintptr_t) readbuf;
        // 通过系统调用到 binder 驱动中的 binder_ioctl 函数,指令为 BINDER_WRITE_READ
        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
        ......
    }
}

// kernel/drivers/staging/android/binder.c
static long binder_ioctl(struct file *filp, 
                        unsigned int cmd, // cmd 就是我们传入的 BINDER_WRITE_READ
                        unsigned long arg // arg 就是我们传入的 bwr
){
    // 获取 binder 驱动的设备节点
    struct binder_proc *proc = filp->private_data;
    struct binder_thread *thread;
    ......
    // 创建 binder_thread
    thread = binder_get_thread(proc);
    ......
    switch (cmd)
    {
        case BINDER_WRITE_READ:
            ret = binder_ioctl_write_read(filp, cmd, arg, thread);
            ......
            break;
        ......
    }
    ......
    return ret;
}

static int binder_ioctl_write_read(struct file *filp,
				unsigned int cmd, unsigned long arg,
				struct binder_thread *thread
){
    struct binder_proc *proc = filp->private_data;
    ......
    void __user *ubuf = (void __user *)arg;
    struct binder_write_read bwr;
    
    // 将描述数据的 binder_write_read 结构体(ubuf)从用户空间拷贝到内核空间(bwr)中去
    if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {
    ......
    // 此时 bwr.write_size = 0,if不命中
    if (bwr.write_size > 0)
    {
        ......
    }
    // 此时 bwr.read_size > 0,if命中
    if (bwr.read_size > 0)
    {
        // 读取binder驱动返回的数据
        ret = binder_thread_read(proc, thread, bwr.read_buffer,
                        bwr.read_size,
                        &bwr.read_consumed,
                        filp->f_flags & O_NONBLOCK);
        ......
    }
    ......
    return ret;
}

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
){
    void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
    // 指向 binder_loop 中 bwr.read_buffer 内存起始地址的指针
    void __user *ptr = buffer + *consumed;
    // 指向 binder_loop 中 bwr.read_buffer 内存结束地址的指针
    void __user *end = buffer + size;
    
    int ret = 0;
    int wait_for_proc_work;

    // 此时 consumed = 0,if命中
    if (*consumed == 0)
    {
        // 将指令 BR_NOOP 拷贝到用户空间中
        if (put_user(BR_NOOP, (uint32_t __user *)ptr))
            return -EFAULT;
        // 指针后移
        ptr += sizeof(uint32_t);
    }

    // 此时 thread->todo = NULL,wait_for_proc_work = true
    wait_for_proc_work = thread->transaction_stack == NULL && list_empty(&thread->todo);
    ......
    if (wait_for_proc_work)
    {
        ......
        // 入参的时候 filp->f_flags & O_NONBLOCK 已经赋值
        // 此时 non_block > 0,执行else
        if (non_block)
        {
            ......
        }
        else
            // 此时 thread->todo = NULL,binder_has_proc_work 返回 false,将 SM 线程挂起
            ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));
    }
    else
    {
        ......
    }
}
复制代码

执行到这后 SM 就会被挂起,等待别的进程与之通信将其唤醒。

唤醒后的 SM 继续执行未完成的 binder_thread_read 函数。

AMS 是如何注册的?

SM 启动完成后就会等待 AMS 与之通信。将 AMS 注册到 SM 中的过程也是 AMS 与 SM 通信的过程。

AMS 的注册是在 SystemServer#main 中执行的。

// frameworks/base/services/java/com/android/server/SystemServer.java
public static void main(String[] args)
{
    new SystemServer().run();
}

private void run()
{
    ......
    // 创建 SystemServiceManager
    mSystemServiceManager = new SystemServiceManager(mSystemContext);
    ......
    startBootstrapServices();
}

private void startBootstrapServices()
{
    ......
    // 通过反射创建 ActivityManagerService.Lifecycle 并获取 AMS 对象
    mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
    ......
    // 为 AMS 启动系统进程
    mActivityManagerService.setSystemProcess();
}

// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void setSystemProcess()
{
    ......
    // 将 AMS 注册到 SM 中
    ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
    ......
}
复制代码

我们接着来看 ServiceManager#addService 函数。

// frameworks/base/core/java/android/os/ServiceManager.java
public static void addService(String name, IBinder service, boolean allowIsolated)
{
    ......
    getIServiceManager().addService(name, service, allowIsolated);
    ......
}

private static IServiceManager getIServiceManager()
{
    if (sServiceManager != null)
    {
        return sServiceManager;
    }
    // 创建 ServiceManagerProxy
    sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
    return sServiceManager;
}

// frameworks/base/core/java/com/android/internal/os/BinderInternal.java
public static final native IBinder getContextObject();

// frameworks/base/core/jni/android_util_Binder.cpp
static const JNINativeMethod gBinderInternalMethods[] = {
    ......
    { "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },
    ......
};

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
    // ProcessState::self():打开 binder驱动并创建 ProcessState(ProcessState是单例的)
    // ProcessState::getContextObject(NULL):创建 BpBinder 对象并返回
    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
    // 创建 BinderProxy 对象并返回
    return javaObjectForIBinder(env, b);
}
复制代码

我们首先来看 ProcessState::self 函数具体做了什么。

// frameworks/native/libs/binder/ProcessState.cpp
sp<ProcessState> ProcessState::self()
{
    Mutex::Autolock _l(gProcessMutex);
    // 单例模式
    if (gProcess != NULL)
    {
        return gProcess;
    }
    // 创建 ProcessState
    gProcess = new ProcessState;
    return gProcess;
}

// BINDER_VM_SIZE 的大小为 1M-8K
#define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))

ProcessState::ProcessState()
    : mDriverFD(open_driver()) // 开启 binder 驱动
    ......
{
    // 如果开启 binder 驱动成功,得到了 binder 驱动设备节点
    if (mDriverFD >= 0)
    {
        // 通过系统调用到 binder 驱动中的 binder_mmap 函数,
        // 在当前进程的用户空间和内核空间之间映射 BINDER_VM_SIZE (1M-8K)大小的内存空间
        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
        ......
    }
    ......
}
复制代码

可以看到在 ProcessState 创建的时候就会开辟共享内存用于之后与 SM 的通信。

我们接着来看 ProcessState::getContextObject 函数具体做了什么。

// frameworks/native/libs/binder/ProcessState.cpp
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
    // BpBinder 对象的 handle 值是0
    return getStrongProxyForHandle(0);
}

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp<IBinder> result;

    AutoMutex _l(mLock);
    // 查找 handle 对应的资源项
    handle_entry* e = lookupHandleLocked(handle);
    if (e != NULL)
    {
        IBinder* b = e->binder;
        // 当 handle 值所对应的 IBinder 不存在或弱引用无效时,当前不存在
        if (b == NULL || !e->refs->attemptIncWeak(this))
        {
            // 当前 handle 值为0,if命中
            if (handle == 0)
            {
                Parcel data;
                // 通过 ping 操作测试 binder 是否准备就绪
                status_t status = IPCThreadState::self()->transact(
                        0, IBinder::PING_TRANSACTION, data, NULL, 0);
                if (status == DEAD_OBJECT)
                   return NULL;
            }
            // 创建 BpBinder 对象,handle 值为0
            b = new BpBinder(handle); 
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
        }
        ......
    }
    return result;
}
复制代码

我们返回到前面的 android_os_BinderInternal_getContextObject 函数中,接着来看 javaObjectForIBinder 函数具体做了什么。

jobject javaObjectForIBinder(JNIEnv* env, 
                            const sp<IBinder>& val // 此时的 val 是 BpBinder
){
    ......
    // 从 gBinderProxyOffsets 中查找 BinderProxy 对象
    // 因为此时 BinderProxy 没有创建过,此时 object 为 null
    jobject object = (jobject)val->findObject(&gBinderProxyOffsets);
    if (object != NULL)
    {
        jobject res = jniGetReferent(env, object);
        if (res != NULL)
        {
            ......
            // 如果当前进程中创建过了 BinderProxy 对象就直接返回
            return res;
        }
        ......
    }
    ......
    // 创建 BinderProxy
    object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);
    if (object != NULL)
    {
        // 将 gBinderProxyOffsets 结构体中的成员变量 mObject 赋值(BpBinder),
        // 记录 BpBinder 对象
        env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
        ......
        // 将 BinderProxy 对象信息添加到 BpBinder 的成员变量 mObjects 中,
        // 将 BinderProxy 与 BpBinder 互相绑定
        val->attachObject(&gBinderProxyOffsets, refObject, jnienv_to_javavm(env), proxy_cleanup);
        ......
        // BinderProxy.mOrgue 成员变量记录死亡通知对象
        env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get()));
        ......
    }
    return object;
}
复制代码

可以看到 BinderProxy 每个进程中只会创建一次。

每个 BinderProxy 对象都会绑定一个 IBinder 对象。此时绑定的是 BpBinder 对象且该 BpBinder 对象的 handle 值是0。

到此 getIServiceManager 函数做了什么我们已经分析完了,现在我们返回 ServiceManager#addService 函数,接着来看 ServiceManagerProxy#addSevice 具体做了什么。

// frameworks/base/core/java/android/os/ServiceManagerNative.java$ServiceManagerProxy.java
public void addService(String name, IBinder service, boolean allowIsolated) throws RemoteException
{
    // 创建 data
    Parcel data = Parcel.obtain();
    // 创建 reply
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IServiceManager.descriptor);
    data.writeString(name);
    // 将 AMS 写入 data
    data.writeStrongBinder(service);
    data.writeInt(allowIsolated ? 1 : 0);
    // mRemote = BinderProxy,相当于调用到 BinderProxy#transact
    mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
    reply.recycle();
    data.recycle();
}
复制代码

AMS 是如何将数据打包的?

我们先来看看 AMS 是如何写入 data 的。

// frameworks/base/core/java/android/os/Parcel.java
public final void writeStrongBinder(IBinder val)
{
    nativeWriteStrongBinder(mNativePtr, val);
}

// frameworks/base/core/jni/android_os_Parcel.cpp
static const JNINativeMethod gParcelMethods[] = {
    ......
    {"nativeWriteStrongBinder", "(JLandroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder},
    ......
}

static void android_os_Parcel_writeStrongBinder(JNIEnv* env, 
                                                jclass clazz, jlong nativePtr, 
                                                jobject object // object 就是传入的 AMS
){
    // 将 Java 层的 Parcel 类型(Java的Parcel)对象强制类型转换成 Native 层的 Parcel 类型对象(Native的Parcel)
    // reinterpret_cast<A*>的作用:将 nativePtr 指向的内存拷贝一份并转换成 A 类型的对象
    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    if (parcel != NULL)
    {
        const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
        ......
    }
}

// frameworks/base/core/jni/android_util_Binder.cpp
sp<IBinder> ibinderForJavaObject(JNIEnv* env,
                                jobject obj // obj 就是传入的 AMS
){
    if (obj == NULL)
        return NULL;
    // 如果 obj 的类型是 Binder,此时 obj 的类型是 Binder,if命中
    if (env->IsInstanceOf(obj, gBinderOffsets.mClass))
    {
        // 从 gBinderOffsets.mObject 成员属性获取 JavaBBinderHolder 对象
        JavaBBinderHolder* jbh = (JavaBBinderHolder*) env->GetLongField(obj, gBinderOffsets.mObject);
        // 通过 JavaBBinderHolder#get 函数创建 JavaBBinder
        return jbh != NULL ? jbh->get(env, obj) : NULL;
    }
    ......
    return NULL;
}
复制代码

AMS 在创建的时候会相应的创建一个 JavaBBinderHolder 对象,并保存在 gBinderOffsets.mObject 中。

在调用 JavaBBinderHolder#get 函数的时候就会创建一个 JavaBBinder。

这个 JavaBBinder 对象的 mObject 字段持有了 AMS。

我们接着来看 Parcel#writeStrongBinder 函数具体干了什么。

status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
    return flatten_binder(ProcessState::self(), val, this);
}

status_t flatten_binder(const sp<ProcessState>& /*proc*/,
    const sp<IBinder>& binder, // binder 就是 ibinderForJavaObject 中返回的 JavaBBinder 对象
    Parcel* out // out 就是 ServiceManagerProxy#addSevice 函数中的 data
){
    // 记录 AMS 的信息
    flat_binder_object obj;
    ......
    if (binder != NULL)
    {
        // 判断 binder 对象是 BpBinder 还是 BBinder,
        // JavaBBinder 是 BBinder,local 不为 NULL,执行 else
        IBinder *local = binder->localBinder();
        if (!local)
        {
            ......
        }
        else
        {
            // 保存 AMS 的信息
            obj.type = BINDER_TYPE_BINDER;
            // local->getWeakRefs() 就是 JavaBBinder 对象
            obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
            obj.cookie = reinterpret_cast<uintptr_t>(local);
        }
    }
    else
    {
        ......
    }
    return finish_flatten_binder(binder, obj, out);
}

inline static status_t finish_flatten_binder(const sp<IBinder>& /*binder*/, 
                                            const flat_binder_object& flat, Parcel* out)
{
    // 将 flat_binder_object 对象写入
    return out->writeObject(flat, false);
}
复制代码

因此我们知道了 ServiceManagerProxy#addSevice 函数中的 data 写入的其实是 JavaBBinder 对象,该 JavaBBinder 对象的 mObject 字段持有了 AMS。

AMS 是如何将数据发送给 SM 的?

我们接着来看 BinderProxy#transact 函数具体做了什么。

// android\frameworks\base\core\java\android\os\Binder.java
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
    ......
    return transactNative(code, data, reply, flags);
}

public native boolean transactNative(int code, Parcel data, Parcel reply,
            int flags) throws RemoteException;
            
// android\frameworks\base\core\jni\android_util_Binder.cpp
static const JNINativeMethod gBinderProxyMethods[] = {
    ......
    {"transactNative", "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", 
            (void*)android_os_BinderProxy_transact},
    ......
};
复制代码

可以看到在 BinderProxy#transact 函数调用了一个 native 函数 transactNativetransactNative 函数对应的是 android_os_BinderProxy_transact 函数。

// android\frameworks\base\core\jni\android_util_Binder.cpp
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
                    jint code, // code 就是 ADD_SERVICE_TRANSACTION
                    jobject dataObj, // dataObj 就是 ServiceManagerProxy#addSevice 中传入的 data
                    jobject replyObj, // replyObj 就是 ServiceManagerProxy#addSevice 中传入的 reply
                    jint flags
){
    ......
    // 将 dataObj 的类型转成 Parcel
    Parcel* data = parcelForJavaObject(env, dataObj);
    ......
    // 将 replyObj 的类型转成 Parcel
    Parcel* reply = parcelForJavaObject(env, replyObj);
    ......
    // 获取 gBinderProxyOffsets.mObject 中保存的 BpBinder 对象
    IBinder* target = (IBinder*) env->GetLongField(obj, gBinderProxyOffsets.mObject);
    ......
    // 调用到 BpBinder 对象的 transact 函数
    status_t err = target->transact(code, *data, reply, flags);
    ......
}
复制代码

我们接着来看 BpBinder#transact 函数。

// android\frameworks\native\libs\binder\BpBinder.cpp
status_t BpBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    ......
    // mHandle = 0
    status_t status = IPCThreadState::self()->transact(mHandle, code, data, reply, flags);
    ......
}
复制代码

我们接着看 IPCThreadState#self 函数做了什么。

// android\frameworks\native\libs\binder\BpBinder.cpp
IPCThreadState* IPCThreadState::self()
{
    ......
    // 创建 IPCThreadState 对象
    return new IPCThreadState;
    ......
}

IPCThreadState::IPCThreadState()
    : mProcess(ProcessState::self()), // 调用 ProcessState::self 函数
      ......
{
    ......
    mIn.setDataCapacity(256); // 设置 mIn 的大小
    mOut.setDataCapacity(256); // 设置 mOut 的大小
}
复制代码

IPCThreadState#self 函数中主要是完成了 IPCThreadState 和 ProcessState 对象的初始化,并通过系统调用到 binder 驱动中的 binder_mmap 函数完成对共享内存的初始化。

接着我们继续看 IPCThreadState#transact 函数中做了什么。

// android\frameworks\native\libs\binder\IPCThreadState.cpp
status_t IPCThreadState::transact(int32_t handle, // handle = 0
                        uint32_t code, // code 就是 ADD_SERVICE_TRANSACTION
                        const Parcel& data, // data 就是 ServiceManagerProxy#addSevice 中传入的 data
                        Parcel* reply, // reply 就是 ServiceManagerProxy#addSevice 中传入的 reply
                        uint32_t flags
){
    // 数据错误检查
    status_t err = data.errorCheck();

    // TF_ACCEPT_FDS = 0x10:允许回复中包含文件描述符 
    // TF_ONE_WAY:当前业务是异步的,不需要等待 
    // TF_ROOT_OBJECT:所包含的内容是根对象 
    // TF_STATUS_CODE:所包含的内容是 32-bit 的状态值
    flags |= TF_ACCEPT_FDS;
    ......
    // 整理数据,将数据写入 mOut 中。
    err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
    ......
    // 判断当前业务是否为异步操作。
    // AIDL默认是同步操作,除非你定义AIDL接口时使用了oneway关键字。
    if ((flags & TF_ONE_WAY) == 0)
    {
        ......
        // reply 不为空
        if (reply)
        {
            // 等待 Binder 驱动回应事件
            err = waitForResponse(reply);
        }
        else
        {
            Parcel fakeReply;
            // 等待 Binder 驱动回应事件
            err = waitForResponse(&fakeReply);
        }
        ......
    }
    else
    {
        // 不等待 Binder 驱动回应事件
        err = waitForResponse(NULL, NULL);
    }
    ......
}
复制代码

mOut 中打包了命令 BC_TRANSACTION (在 mOut 中的地址高位)和我们要发送给 SM 的数据(在 mOut 中的地址低位)。

继续看到 IPCThreadState#waitForResponse 函数。

// android\frameworks\native\libs\binder\IPCThreadState.cpp
status_t IPCThreadState::waitForResponse(
                    Parcel *reply, // reply 就是 ServiceManagerProxy#addSevice 中传入的 reply
                    status_t *acquireResult
){
    uint32_t cmd;
    int32_t err;
    // 循环等待结果
    while (1)
    {
        // 调用 talkWithDriver 函数发送指令给 binder 驱动
        if ((err=talkWithDriver()) < NO_ERROR) break;
        ......
		// 如果 mIn 中没有数据,就 continue
        if (mIn.dataAvail() == 0) continue;
        ......
    }
    ......
}
复制代码

我们接着来看 IPCThreadState#talkWithDriver 函数中是如何发送指令给 binder 驱动的。

// android\frameworks\native\libs\binder\IPCThreadState.cpp
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
    ......
    // mIn 是宏定义的 Parcel 变量,此时 mIn 未进行赋值
    // mIn.dataPosition() = mIn.dataSize() = 0,needRead为true
    const bool needRead = mIn.dataPosition() >= mIn.dataSize();
    ......
    const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
    
    bwr.write_size = outAvail;
    // 在 bwr 中填写需要写的指令大小和内容
    bwr.write_buffer = (uintptr_t)mOut.data();

    // 如果需要读数据
    if (doReceive && needRead)
    {
        // dataCapacity = 256
        bwr.read_size = mIn.dataCapacity();
        // 此时的 mIn.data() = 0
        bwr.read_buffer = (uintptr_t)mIn.data();
    }
    else // 不需要读数据就设置为零。
         // 这样在 binder_ioctl_write_read 函数中就不会执行 binder_thread_read
    {
        bwr.read_size = 0;
        bwr.read_buffer = 0;
    }
    ......
    bwr.write_consumed = 0;
    bwr.read_consumed = 0;
    // 循环发送指令给 binder 驱动直至成功
    do {
        ......
        // 给 Binder 驱动发送命令 BC_TRANSACTION,
        // 通过系统调用到 Binder 驱动的 binder_ioctl 方法,进入内核态
        if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
            err = NO_ERROR;
        else
            err = -errno;
        ......
    } while (err == -EINTR); // 只有当 ioctl 发生错误后while循环条件才会成立,
                             // 因此如果发送成功就只执行一次
    ......
}
复制代码

当调用了 ioctl 函数后,经过系统调用(Syscall)到 Binder 驱动中的 binder_ioctl 函数,命令为 BINDER_WRITE_READ

// kernel\drivers\staging\android\binder.c
static long binder_ioctl(struct file *filp, unsigned int cmd, 
                        unsigned long arg // arg 是用来描述 mOut 的 bwr 的地址值
){
    ......
    void __user *ubuf = (void __user *)arg;
    ......
    // 获取命令(BINDER_WRITE_READ)
    trace_binder_ioctl(cmd, arg);
    ......
    switch (cmd)
    {
        case BINDER_WRITE_READ:
            ret = binder_ioctl_write_read(filp, cmd, arg, thread);
            ......
    }
}
复制代码

继续看到 binder_ioctl_write_read 函数。

// kernel\drivers\staging\android\binder.c
static int binder_ioctl_write_read(struct file *filp,
				unsigned int cmd, unsigned long arg,
				struct binder_thread *thread)
{
    struct binder_proc *proc = filp->private_data;
    ......
    void __user *ubuf = (void __user *)arg;
    struct binder_write_read bwr;

    // 将 binder_write_read 结构体(ubuf)从用户空间拷贝到内核空间(bwr)中去
    if (copy_from_user(&bwr, ubuf, sizeof(bwr)))
    {
        ret = -EFAULT;
        goto out;
    }
    ......
    // 此时 bwr.write_size > 0,if命中
    if (bwr.write_size > 0)
    {
        // 发送指令给 binder 驱动
        ret = binder_thread_write(proc, thread,
                        bwr.write_buffer,
                        bwr.write_size,
                        &bwr.write_consumed);
        ......
    }
    // 此时 bwr.read_size > 0,if命中
    if (bwr.read_size > 0)
    {
        // 读取 binder 驱动返回的指令
        ret = binder_thread_read(proc, thread, bwr.read_buffer,
                        bwr.read_size,
                        &bwr.read_consumed,
                        filp->f_flags & O_NONBLOCK);
        ......
    }
    ......
out:
    return ret;
}
复制代码

我们先来看 binder_thread_write 函数具体做了什么。

// kernel\drivers\staging\android\binder.c
static int binder_thread_write(struct binder_proc *proc,
			struct binder_thread *thread,
			binder_uintptr_t binder_buffer, size_t size,
			binder_size_t *consumed)
{
    uint32_t cmd;
    struct binder_context *context = proc->context;
    void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
    // 指向 mOut 内存起始地址的指针
    void __user *ptr = buffer + *consumed;
    // 指向 mOut 内存结束地址的指针
    void __user *end = buffer + size;
    
    // 遍历 mOut 内存,取出指令
    while (ptr < end && thread->return_error == BR_OK)
    {
        // 将 mOut 中写入的命令从用户空间拷贝到内核空间中的 cmd,
        // 此时 cmd = BC_TRANSACTION
        if (get_user(cmd, (uint32_t __user *)ptr))
            return -EFAULT;
        // 指针后移
        ptr += sizeof(uint32_t);
        ......
        switch (cmd)
        {
            ......
            case BC_TRANSACTION:
            case BC_REPLY:
            {
                struct binder_transaction_data tr;
                // 将要发送给 SM 的数据从用户空间拷贝到内核空间中的 binder_transaction_data 结构体
                if (copy_from_user(&tr, ptr, sizeof(tr)))
                    return -EFAULT;
                // 指针后移
                ptr += sizeof(tr);
                // 调用 binder_transaction 函数
                binder_transaction(proc, thread, &tr, cmd == BC_REPLY, 0);
                break;
            }
            ......
        }
        ......
    }
    ......
}
复制代码

前面在 binder_ioctl_write_read 函数中拷贝的只是用于描述 mOut 的结构体,结构体中保存的只是 mOut 的起始地址。而 binder_thread_write 函数中才真正将 mOut 中打包的数据拷贝到内核空间。

这里还不是真正意义上的一次拷贝。

继续看到 binder_transaction 函数。

// kernel\drivers\staging\android\binder.c
static void binder_transaction(struct binder_proc *proc,
			       struct binder_thread *thread,
			       struct binder_transaction_data *tr, 
                               int reply, // 此时 reply = false
			       binder_size_t extra_buffers_size)
{
    ......
    struct binder_transaction *t;
    struct binder_work *tcomplete;
    ......
    struct binder_proc *target_proc;
    struct binder_thread *target_thread = NULL;
    struct binder_node *target_node = NULL;
    struct list_head *target_list;
    wait_queue_head_t *target_wait;
    ......
    // 此处 reply 为 false(cmd == BC_TRANSACTION)
    if (reply)
    {
        ......
    }
    else
    {
        // tr->target.handle = 0,执行 else
        if (tr->target.handle)
        {
            ......
        }
        else
        {
            // 获取 SM 的 binder_node 节点
            target_node = context->binder_context_mgr_node;
            ......
        }
        ......
        // 获取 SM 的 binder_proc
        target_proc = target_node->proc;
        ......
    }
    // 获取 SM 的 todo 队列和 wait 队列
    target_list = &target_proc->todo;
    target_wait = &target_proc->wait;
    ......
    // 生成一个 binder_transaction 变量(即变量 t),
    // 用于描述本次要进行的 transaction(最后将其加入 target_thread->todo)。
    // 这样当目标对象被唤醒时,它就可以从这个队列中取出需要做的工作。
    t = kzalloc(sizeof(*t), GFP_KERNEL);
    ......
    // 生成一个 binder_work 变量(即变量 tcomplete),用于说明 AMS 有一个未完成的工作
    tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);
    ......
    // 此时 if 命中
    if (!reply && !(tr->flags & TF_ONE_WAY))
        // 非 oneway(同步)的通信方式,把当前 thread 保存到 transaction 的 from 字段
        t->from = thread;
    else
        t->from = NULL;
    ......
    // 记录此次通信的目标进程
    t->to_proc = target_proc;
    ......
    // 此次通信 code = ADD_SERVICE_TRANSACTION
    t->code = tr->code;
    // 此次通信 flags = 0
    t->flags = tr->flags;
    ......
    // 从 SM 进程中分配 buffer
    // (为完成本条 transaction 申请内存,从 binder_mmap 开辟的空间中申请内存)
    t->buffer = binder_alloc_buf(target_proc, tr->data_size,
            tr->offsets_size, extra_buffers_size,
            !reply && (t->flags & TF_ONE_WAY));
    ......
    // 记录 SM 的 binder_node
    t->buffer->target_node = target_node;
    ......
    // 拷贝用户空间的 binder_transaction_data 中 ptr.buffer 指针到内核空间
    if (copy_from_user(t->buffer->data, (const void __user *)(uintptr_t)
                    tr->data.ptr.buffer, tr->data_size))
    ......
    // 拷贝用户空间的 binder_transaction_data 中 ptr.offsets 指针到内核空间
    if (copy_from_user(offp, (const void __user *)(uintptr_t)
                    tr->data.ptr.offsets, tr->offsets_size))
    ......
    // 此时 cmd = BC_TRANSACTION,cmd != BC_REPLY,reply = false
    if (reply)
    {
        ......
    }
    else if(!(t->flags & TF_ONE_WAY)) // 操作是同步的,命中
    {
        ......
        // 记录本次的 transaction,以备后期查询
        // (SM 通过这个知道是谁调用的,从而返回数据)
        thread->transaction_stack = t;
    }
    else
    {
        ......
    }
    // 设置 t 的类型为 BINDER_WORK_TRANSACTION
    t->work.type = BINDER_WORK_TRANSACTION;
    // 将 t 加入 SM 进程的 todo 队列
    list_add_tail(&t->work.entry, target_list);
    // 设置 binder_work 的类型为 BINDER_WORK_TRANSACTION_COMPLETE
    tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
    // 将 tcomplete 加入 AMS 线程的 todo 队列
    list_add_tail(&tcomplete->entry, &thread->todo);
    // 此时 SM 被挂起,target_wait != NULL,if命中
    if (target_wait)
        // 唤醒 SM 进程
        wake_up_interruptible(target_wait);
    return;
    ......
}
复制代码

binder_transaction 函数中主要做了几件事:

  1. 获取到服务端进程的 binder_proc 结构体。
  2. 生成一个 binder_transaction 变量(给 Service 的)和一个 binder_work 变量(给 Client 的)来保存信息。
  3. 将 mOut 中打包的数据拷贝到经过 binder_mmap 开辟的共享内存中(重点,一次拷贝是在这)。
  4. 将 binder_transaction 变量添加到目标服务端进程的 work 队列,唤醒目标服务端进程。
  5. 将 binder_work 变量添加到当前调用方线程的 todo 队列,让当前调用方线程挂起等待。

所以在这个函数中才真正的做到了 IPC 通信传输。

我们知道 SM 和 AMS 两个进程是异步执行代码的,因此我们先来看 AMS 进程接下来做了什么。

在 AMS 进程中,当 binder_transaction 函数执行完成返回后,binder_thread_write 函数执行结束,接着执行 binder_thread_read 函数。

// kernel\drivers\staging\android\binder.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)
{
    void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
    // 指向 mIn 内存起始地址的指针
    void __user *ptr = buffer + *consumed;
    // 指向 mIn 内存结束地址的指针
    void __user *end = buffer + size;

    int ret = 0;
    int wait_for_proc_work;
    ......
retry:
    // 1. thread->todo 不为空,wait_for_proc_work 为 false
    // 2. thread->todo 为空,wait_for_proc_work 为 true
    wait_for_proc_work = thread->transaction_stack == NULL && list_empty(&thread->todo);
    // 1. 执行 else
    // 2. 执行 if
    if (wait_for_proc_work)
    {
        ......
        if (non_block) // 入参的时候 filp->f_flags & O_NONBLOCK 已经赋值
                       // 此时 non_block > 0,执行else
        {
            ......
        }
        else
            // 2. thread->todo 为空,binder_has_thread_work 返回 false,将 AMS 线程挂起
            ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));
    }
    else
    {
        if (non_block) // 入参的时候 filp->f_flags & O_NONBLOCK 已经赋值
                       // 此时 non_block > 0,执行else
        {
            ......
        }
        else
            // 1. thread->todo 不为空,binder_has_thread_work 返回 true,不会将 AMS 线程挂起
            ret = wait_event_freezable(thread->wait, binder_has_thread_work(thread));
    }
    ......
    // 1. 线程没有挂起,继续执行 while 循环
    while (1)
    {
        uint32_t cmd;
        struct binder_transaction_data tr;
        struct binder_work *w;
        struct binder_transaction *t = NULL;
        
        // 1. 在 binder_transaction 函数中添加了一个 binder_work,此时 thread->todo 不为空,if 命中
        // 2. 在执行 BINDER_WORK_TRANSACTION_COMPLETE 指令的时候将 binder_work 删除了,
        // 此时 thread->todo 为空,执行else
        if (!list_empty(&thread->todo))
        {
            // 1. 取出 binder_work
            w = list_first_entry(&thread->todo, struct binder_work, entry);
        }
        else
        {
            // 2. 此时 if 命中
            if (ptr - buffer == 4 && !(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN))
                // 2. 返回 retry 处执行代码
                goto retry;
            break;
        }
        ......
        // 1. 此时 w->type 为 BINDER_WORK_TRANSACTION_COMPLETE
        switch (w->type)
        {
            ......
            case BINDER_WORK_TRANSACTION_COMPLETE:
            {
                // 1. 更改指令 BR_TRANSACTION_COMPLETE
                cmd = BR_TRANSACTION_COMPLETE;
                // 1. 将指令拷贝到 mIn 中
                if (put_user(cmd, (uint32_t __user *)ptr))
                    return -EFAULT;
                // 1. 指针后移
                ptr += sizeof(uint32_t);
                ......
                // 1. 将当前的 binder_work 从 thread->todo 中删除
                list_del(&w->entry);
                // 1. 释放 binder_work 的内存
                kfree(w);
                ......
            } break;
            ......
        }
        // 1. 此时 t = null,if 命中
        if (!t)
            continue;
        ......
    }
    *consumed = ptr - buffer;
    ......
    return 0;
}
复制代码

binder_thread_read 函数中 while 循环会执行两次,所以代码中的注释写了序号,序号对应着第几次 while 循环。

此时 AMS 就被挂起了,等待 SM 进程返回数据后唤醒。当 AMS 被唤醒后就从此处的 binder_thread_read 函数开始继续执行。

SM 进程被唤醒后做了什么?

我们接下来看 SM 进程被唤醒后做了什么。

在 SM 进程中,当 binder_transaction 函数执行完成返回后,SM 进程被唤醒,继续执行未完成的 binder_thread_read 函数。

// kernel\drivers\staging\android\binder.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)
{
    ......
    while (1)
    {
        uint32_t cmd;
        struct binder_transaction_data tr;
        struct binder_work *w;
        struct binder_transaction *t = NULL;
        ......
        // 在 binder_transaction 函数中添加了一个 binder_transaction,此时 proc->todo 不为空
        else if (!list_empty(&proc->todo) && wait_for_proc_work)
        {
            // 取出 binder_transaction
            w = list_first_entry(&proc->todo, struct binder_work, entry);
        }
        ......
        // 此时 w->type 为 BINDER_WORK_TRANSACTION
        switch (w->type)
        {
            ......
            case BINDER_WORK_TRANSACTION:
            {
                t = container_of(w, struct binder_transaction, work);
            } break;
            ......
        }
        // 此时 t != null,if不命中
        if (!t)
            continue;
        ......
        // 此时 t->buffer->target_node 不为空,if命中
        if (t->buffer->target_node)
        {
            struct binder_node *target_node = t->buffer->target_node;
            tr.target.ptr = target_node->ptr;
            tr.cookie =  target_node->cookie;
            ......
            // 指令更改为 BR_TRANSACTION
            cmd = BR_TRANSACTION;
        }
        else
        {
            ......
        }
        
        // t->code = ADD_SERVICE_TRANSACTION
        tr.code = t->code;
        // t->flags = 0
        tr.flags = t->flags;
        
        // 此时 t->from 不为 NULL,if 命中
        if (t->from)
        {
            struct task_struct *sender = t->from->proc->tsk;
            // 获取 AMS 线程的 pid 并记录
            tr.sender_pid = task_tgid_nr_ns(sender, task_active_pid_ns(current));
        }
        else
        {
            ......
        }
        // 将 binder_transaction 结构体(t)拷贝到 binder_transaction_data 结构体(tr)
        tr.data_size = t->buffer->data_size;
        tr.offsets_size = t->buffer->offsets_size;
        tr.data.ptr.buffer = (binder_uintptr_t)((uintptr_t)t->buffer->data + proc->user_buffer_offset);
        tr.data.ptr.offsets = tr.data.ptr.buffer + ALIGN(t->buffer->data_size, sizeof(void *));
        
        // 将指令 BR_TRANSACTION 拷贝到用户空间(binder_loop 中的 bwr.read_buffer)
        if (put_user(cmd, (uint32_t __user *)ptr))
            return -EFAULT;
        // 指针后移
        ptr += sizeof(uint32_t);
        
        // 将描述数据的 tr 结构体拷贝到用户空间(binder_loop 中的 bwr.read_buffer)
        if (copy_to_user(ptr, &tr, sizeof(tr)))
            return -EFAULT;
        // 指针后移
        ptr += sizeof(tr);
        ......
        // 此时 if 命中
        if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY))
        {
            t->to_parent = thread->transaction_stack;
            t->to_thread = thread;
            // 将 t 保存在 SM 线程中的 transaction_stack 中
            thread->transaction_stack = t;
        }
        else
        {
            ......
        }
        // 跳出循环
        break;
        ......
    }
    *consumed = ptr - buffer;
    ......
    return 0;
}
复制代码

binder_thread_read 函数执行完成后,binder_ioctl_write_read 函数也执行完成返回,我们返回到 binder_loop 函数,继续执行。

// frameworks/native/cmds/servicemanager/binder.c
void binder_loop(struct binder_state *bs, binder_handler func)
{
    ......
    for (;;)
    {
        ......
        res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
        ......
    }
}
复制代码

我们接着看到 binder_parse 函数。

// frameworks/native/cmds/servicemanager/binder.c
int binder_parse(struct binder_state *bs, 
                struct binder_io *bio,
                uintptr_t ptr, // ptr 就是指向 binder_loop 中 bwr.read_buffer 的起始地址
                size_t size, // size 就是 binder_loop 中的 bwr.read_size
                binder_handler func
){
    int r = 1;
    // 指向 binder_loop 中的 bwr.read_buffer 内存结束地址的指针
    uintptr_t end = ptr + (uintptr_t) size;

    while (ptr < end)
    {
        // bwr.read_buffer 中前 uint32_t 大小的内存是指令,当前指令是 BR_TRANSACTION
        uint32_t cmd = *(uint32_t *) ptr;
        // 指针后移
        ptr += sizeof(uint32_t);
        ......
        switch(cmd)
        {
            ......
            case BR_TRANSACTION:
            {
                // 将 binder_loop 中 bwr.read_buffer 指向的剩余内存转换成 binder_transaction_data 结构体
                struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
                ......
                // 此时 func = service_manager#svcmgr_handler,if 命中
                if (func)
                {
                    unsigned rdata[256/4];
                    struct binder_io msg;
                    struct binder_io reply;
                    int res;
                    // 初始化 reply
                    bio_init(&reply, rdata, sizeof(rdata), 4);
                    // 初始化 msg,将 txn 中的数据拷贝到 msg 中
                    bio_init_from_txn(&msg, txn);
                    // 执行 service_manager#svcmgr_handler 函数
                    res = func(bs, txn, &msg, &reply);
                    // 将 reply 发给 binder 驱动
                    binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
                }
                // 指针后移
                ptr += sizeof(*txn);
                break;
            }
            ......
        }
    }
    return r;
}
复制代码

我们接着看到 service_manager#svcmgr_handler 函数。

// frameworks/native/cmds/servicemanager/service_manager.c
int svcmgr_handler(struct binder_state *bs,
                   struct binder_transaction_data *txn,
                   struct binder_io *msg,
                   struct binder_io *reply
){
    struct svcinfo *si;
    uint16_t *s;
    size_t len;
    uint32_t handle;
    uint32_t strict_policy;
    int allow_isolated;
    ......
    // 此时 txn->code = ADD_SERVICE_TRANSACTION = 3 = SVC_MGR_ADD_SERVICE
    switch(txn->code)
    {
        ......
        case SVC_MGR_ADD_SERVICE:
            // 获取 AMS 的名称
            s = bio_get_string16(msg, &len);
            ......
            // 获取 AMS 的 handle 值
            handle = bio_get_ref(msg);
            allow_isolated = bio_get_uint32(msg) ? 1 : 0;
            // 在 SM 中记录 AMS
            if (do_add_service(bs, s, len, handle, txn->sender_euid,
                allow_isolated, txn->sender_pid))
                return -1;
            break;
        ......
    }
    // 此时 reply 中没有数据
    bio_put_uint32(reply, 0);
    return 0;
}

int do_add_service(struct binder_state *bs,
                   const uint16_t *s, size_t len,
                   uint32_t handle, uid_t uid, int allow_isolated,
                   pid_t spid
){
    // 在 SM 中用 svcinfo 结构体保存注册过的 Service 的信息
    struct svcinfo *si;
    ......
    // 查找 AMS 是否在 SM 注册过
    si = find_svc(s, len);
    // 如果 AMS 已经注册过了
    if (si)
    {
        if (si->handle)
        {
            ......
            // 将当前这个 svcinfo 结构体中的记录的 handle 值清空
            svcinfo_death(bs, si);
        }
        // 对当前这个 svcinfo 结构体中的 handle 值重新赋值
        si->handle = handle;
    }
    else // 如果 AMS 没注册过
    {
        // 创建一个新的 svcinfo 结构体
        si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
        ......
        si->handle = handle;
        si->len = len;
        // 拷贝 AMS 信息
        memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
        si->name[len] = '\0';
        si->death.func = (void*) svcinfo_death;
        si->death.ptr = si;
        si->allow_isolated = allow_isolated;
        // 将创建的 svcinfo 结构体添加到 svclist 中
        si->next = svclist;
        svclist = si;
    }
    // 以 BC_ACQUIRE 命令,handle 为目标的信息,通过 ioctl 发送给 binder 驱动,
    // 使 binder_ref 强引用加1操作
    binder_acquire(bs, handle);
    // 以 BC_REQUEST_DEATH_NOTIFICATION 命令的信息,通过 ioctl 发送给 binder 驱动,
    // 主要进行清理内存等收尾工作
    binder_link_to_death(bs, handle, &si->death);
    return 0;
}
复制代码

service_manager#svcmgr_handler 函数中主要将 AMS 记录到了 SM 中。

我们接着来看 binder_send_reply 函数。

// frameworks/native/cmds/servicemanager/binder.c
void binder_send_reply(struct binder_state *bs,
                       struct binder_io *reply, // 此时 reply 中没有数据
                       binder_uintptr_t buffer_to_free, // 用户空间中开辟的共享内存的起始地址
                       int status // status = 0
){
    struct {
        uint32_t cmd_free; // 占高位
        binder_uintptr_t buffer;
        uint32_t cmd_reply; // 占低位
        struct binder_transaction_data txn;
    } __attribute__((packed)) data;

    data.cmd_free = BC_FREE_BUFFER; // free buffer 命令
    data.buffer = buffer_to_free;
    data.cmd_reply = BC_REPLY; // reply 命令
    data.txn.target.ptr = 0;
    data.txn.cookie = 0;
    data.txn.code = 0;
    
    // status = 0,执行 else
    if (status)
    {
        ......
    }
    else
    {
        data.txn.flags = 0;
        data.txn.data_size = reply->data - reply->data0;
        data.txn.offsets_size = ((char*) reply->offs) - ((char*) reply->offs0);
        data.txn.data.ptr.buffer = (uintptr_t)reply->data0;
        data.txn.data.ptr.offsets = (uintptr_t)reply->offs0;
    }
    // 向 binder 驱动通信,执行指令
    binder_write(bs, &data, sizeof(data));
}

int binder_write(struct binder_state *bs, void *data, size_t len)
{
    struct binder_write_read bwr;
    int res;

    bwr.write_size = len;
    bwr.write_consumed = 0;
    bwr.write_buffer = (uintptr_t) data;
    bwr.read_size = 0;
    bwr.read_consumed = 0;
    bwr.read_buffer = 0;
    
    // 通过系统调用到 binder 驱动中的 binder_ioctl 函数,指令为 BINDER_WRITE_READ
    res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
    ......
    return res;
}

// kernel/drivers/staging/android/binder.c
static int binder_ioctl_write_read(struct file *filp,
				unsigned int cmd, unsigned long arg,
				struct binder_thread *thread)
{
    int ret = 0;
    struct binder_proc *proc = filp->private_data;
    ......
    void __user *ubuf = (void __user *)arg;
    struct binder_write_read bwr;
    ......
    // 将 binder_write_read 结构体(ubuf)从用户空间拷贝到内核空间(bwr)中去
    if (copy_from_user(&bwr, ubuf, sizeof(bwr)))
    {
        ret = -EFAULT;
        goto out;
    }
    ......
    if (bwr.write_size > 0)
    {
        // 发送指令给 binder 驱动
        ret = binder_thread_write(proc, thread,
                                bwr.write_buffer,
                                bwr.write_size,
                                &bwr.write_consumed);
        ......
    }
    // 此时 bwr.read_size = 0,if 不命中
    if (bwr.read_size > 0)
    {
	......
    }
    ......
out:
    return ret;
}

static int binder_thread_write(struct binder_proc *proc,
			struct binder_thread *thread,
			binder_uintptr_t binder_buffer, // binder_buffer 就是 binder_send_reply 中的 data
                        size_t size, // size 就是 binder_send_reply 中的 data 的内存大小
			binder_size_t *consumed
){
    uint32_t cmd;
    struct binder_context *context = proc->context;
    void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
    // 指向 data 内存起始地址的指针
    void __user *ptr = buffer + *consumed;
    // 指向 data 内存结束地址的指针
    void __user *end = buffer + size;
    
    while (ptr < end && thread->return_error == BR_OK)
    {
        // 从 data 中读取指令
        if (get_user(cmd, (uint32_t __user *)ptr))
            return -EFAULT;
        // 指针后移
        ptr += sizeof(uint32_t);
        // cmd 先是 BC_FREE_BUFFER,再是 BC_REPLY
        switch (cmd)
        {
            ......
            case BC_FREE_BUFFER:
            {
                // 在这里会将 data.buffer 所指向的内存区域中的数据清空,在这里就不多分析了
                ......
                break;
            }
            ......
            case BC_TRANSACTION:
            case BC_REPLY:
            {
                struct binder_transaction_data tr;
                // 将要发送给 AMS 的数据从用户空间拷贝到内核空间中的 binder_transaction_data 结构体
                if (copy_from_user(&tr, ptr, sizeof(tr)))
                    return -EFAULT;
                // 指针后移
                ptr += sizeof(tr);
                // 调用 binder_transaction 函数
                binder_transaction(proc, thread, &tr, cmd == BC_REPLY, 0);
                break;
            }
            ......
        }
        ......
    }
    return 0;
}
复制代码

到了这里就会再次调用 binder_transaction 函数与 AMS 进程进行通信,通知 AMS 注册成功。

// kernel\drivers\staging\android\binder.c
static void binder_transaction(struct binder_proc *proc,
			       struct binder_thread *thread,
			       struct binder_transaction_data *tr, 
                               int reply, // 此时 reply = true
			       binder_size_t extra_buffers_size)
{
    ......
    struct binder_transaction *t;
    struct binder_work *tcomplete;
    ......
    struct binder_proc *target_proc;
    struct binder_thread *target_thread = NULL;
    struct binder_node *target_node = NULL;
    struct list_head *target_list;
    wait_queue_head_t *target_wait;
    ......
    // 此处 reply 为 true(cmd == BC_REPLY)
    if (reply)
    {
        // 获取记录在 thread->transaction_stack 中的 binder_transaction 结构体
        in_reply_to = thread->transaction_stack;
        ......
        thread->transaction_stack = in_reply_to->to_parent;
        // in_reply_to->from = AMS 线程
        target_thread = in_reply_to->from;
        ......
        target_proc = target_thread->proc;
    }
    else
    {
        ......
    }
    // 此时 target_thread != NULL,if 命中
    if (target_thread)
    {
        // 获取 AMS 线程的 pid 值
        e->to_thread = target_thread->pid;
        // 获取 AMS 线程的 todo 队列和 wait 队列
        target_list = &target_thread->todo;
        target_wait = &target_thread->wait;
    }
    else
    {
        ......
    }
    ......
    // 生成一个 binder_transaction 变量(即变量 t),
    // 用于描述本次要进行的 transaction(最后将其加入 target_thread->todo)。
    // 这样当目标对象被唤醒时,它就可以从这个队列中取出需要做的工作。
    t = kzalloc(sizeof(*t), GFP_KERNEL);
    ......
    // 生成一个 binder_work 变量(即变量 tcomplete),用于说明 AMS 有一个未完成的工作
    tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);
    ......
    // 此时 if 不命中,执行 else
    if (!reply && !(tr->flags & TF_ONE_WAY))
        ......
    else
        t->from = NULL;
    ......
    // 记录此次通信的目标进程(AMS)
    t->to_proc = target_proc;
    ......
    // 此次通信 code = 0
    t->code = tr->code;
    // 此次通信 flags = 0
    t->flags = tr->flags;
    ......
    // 从 AMS 进程中分配 buffer
    // (为完成本条 transaction 申请内存,从 binder_mmap 开辟的空间中申请内存)
    t->buffer = binder_alloc_buf(target_proc, tr->data_size,
            tr->offsets_size, extra_buffers_size,
            !reply && (t->flags & TF_ONE_WAY));
    ......
    // 记录 AMS 的 binder_node,此时 target_node = NULL
    t->buffer->target_node = target_node;
    ......
    // 拷贝用户空间的 binder_transaction_data 中 ptr.buffer 指针到内核空间
    if (copy_from_user(t->buffer->data, (const void __user *)(uintptr_t)
                    tr->data.ptr.buffer, tr->data_size))
    ......
    // 拷贝用户空间的 binder_transaction_data 中 ptr.offsets 指针到内核空间
    if (copy_from_user(offp, (const void __user *)(uintptr_t)
                    tr->data.ptr.offsets, tr->offsets_size))
    ......
    // 此时 cmd = BC_REPLY,reply = true
    if (reply)
    {
        ......
        // 清空数据,释放缓存
        binder_pop_transaction(target_thread, in_reply_to);
    }
    else if(!(t->flags & TF_ONE_WAY))
    {
        ......
    }
    else
    {
        ......
    }
    // 设置 t 的类型为 BINDER_WORK_TRANSACTION
    t->work.type = BINDER_WORK_TRANSACTION;
    // 将 t 加入 AMS 线程的 todo 队列
    list_add_tail(&t->work.entry, target_list);
    // 设置 binder_work 的类型为 BINDER_WORK_TRANSACTION_COMPLETE
    tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
    // 将 tcomplete 加入 SM 进程的 todo 队列
    list_add_tail(&tcomplete->entry, &thread->todo);
    // 此时 AMS 被挂起,target_wait != NULL,if命中
    if (target_wait)
        // 唤醒 AMS 进程
        wake_up_interruptible(target_wait);
    return;
    ......
}
复制代码

我们先来看 SM 进程接下来做了什么。

在 SM 进程中,当 binder_transaction 函数执行完成返回后,一直返回到 binder_loop 函数,经过循环再次调用 ioctl 函数读取 binder 驱动的指令。

我们直接看到 binder_thread_read 函数。

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
){
    void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
    // 指向 binder_loop 中的 bwr.read_buffer 内存起始地址的指针
    void __user *ptr = buffer + *consumed;
    // 指向 binder_loop 中的 bwr.read_buffer 内存结束地址的指针
    void __user *end = buffer + size;

    int ret = 0;
    int wait_for_proc_work;
    ......
retry:
    // 1. thread->todo 不为空,wait_for_proc_work 为 false
    // 2. thread->todo 为空,wait_for_proc_work 为 true
    wait_for_proc_work = thread->transaction_stack == NULL && list_empty(&thread->todo);
    ......
    // 1. 执行 else
    // 2. 执行 if
    if (wait_for_proc_work)
    {
        ......
        if (non_block) // 入参的时候 filp->f_flags & O_NONBLOCK 已经赋值
                       // 此时 non_block > 0,执行else
        {
            ......
        }
        else
            // 2. thread->todo 为空,binder_has_thread_work 返回 false,将 SM 线程挂起
            ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));
    }
    else
    {
        if (non_block) // 入参的时候 filp->f_flags & O_NONBLOCK 已经赋值
                       // 此时 non_block > 0,执行 else
        {
            ......
        }
        else
            // 1. thread->todo 不为空,binder_has_thread_work 返回 true,不会将 SM 线程挂起
            ret = wait_event_freezable(thread->wait, binder_has_thread_work(thread));
    }
    ......
    // 1. 线程没有挂起,继续执行 while 循环
    while (1)
    {
        uint32_t cmd;
        struct binder_transaction_data tr;
        struct binder_work *w;
        struct binder_transaction *t = NULL;
        
        // 1. 在 binder_transaction 函数中添加了一个 binder_work,此时 thread->todo 不为空,if 命中
        // 2. 在执行 BINDER_WORK_TRANSACTION_COMPLETE 指令的时候将 binder_work 删除了,
        // 此时 thread->todo 为空,执行else
        if (!list_empty(&thread->todo))
        {
            // 1. 取出 binder_work
            w = list_first_entry(&thread->todo, struct binder_work, entry);
        }
        else
        {
            // 2. 此时 if 命中
            if (ptr - buffer == 4 && !(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN))
                // 2. 返回 retry 处执行代码
                goto retry;
            break;
        }
        ......
        // 1. 此时 w->type 为 BINDER_WORK_TRANSACTION_COMPLETE
        switch (w->type)
        {
            ......
            case BINDER_WORK_TRANSACTION_COMPLETE:
            {
                // 1. 更改指令 BR_TRANSACTION_COMPLETE
                cmd = BR_TRANSACTION_COMPLETE;
                // 1. 将指令拷贝到 binder_loop 中的 bwr.read_buffer
                if (put_user(cmd, (uint32_t __user *)ptr))
                    return -EFAULT;
                // 1. 指针后移
                ptr += sizeof(uint32_t);
                ......
                // 1. 将当前的 binder_work 从 thread->todo 中删除
                list_del(&w->entry);
                // 1. 释放 binder_work 的内存
                kfree(w);
                ......
            } break;
            ......
        }
        // 1. 此时 t = null,if 命中
        if (!t)
            continue;
        ......
    }
    *consumed = ptr - buffer;
    ......
    return 0;
}
复制代码

binder_thread_read 函数中 while 循环会执行两次,所以代码中的注释写了序号,序号对应着第几次 while 循环。

此时 SM 就被挂起了,等待其他进程与之通信后唤醒。当 SM 被唤醒后就从此处的 binder_thread_read 函数开始继续执行。

AMS 进程被唤醒后做了什么?

我们接下来看 AMS 进程被唤醒后做了什么。

在 AMS 进程中,当 binder_transaction 函数执行完成返回后,AMS 进程被唤醒,继续执行未完成的 binder_thread_read 函数。

// kernel\drivers\staging\android\binder.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)
{
    ......
    while (1)
    {
        uint32_t cmd;
        struct binder_transaction_data tr;
        struct binder_work *w;
        struct binder_transaction *t = NULL;
        ......
        // 在 binder_transaction 函数中添加了一个 binder_transaction,此时 proc->todo 不为空
        else if (!list_empty(&proc->todo) && wait_for_proc_work)
        {
            // 取出 binder_transaction
            w = list_first_entry(&proc->todo, struct binder_work, entry);
        }
        ......
        // 此时 w->type 为 BINDER_WORK_TRANSACTION
        switch (w->type)
        {
            ......
            case BINDER_WORK_TRANSACTION:
            {
                t = container_of(w, struct binder_transaction, work);
            } break;
            ......
        }
        // 此时 t != null,if不命中
        if (!t)
            continue;
        ......
        // 此时 t->buffer->target_node 为空,if 不命中
        if (t->buffer->target_node)
        {
            ......
        }
        else
        {
            tr.target.ptr = 0;
            tr.cookie = 0;
            // 指令更改为 BR_REPLY
            cmd = BR_REPLY;
        }
        
        // t->code = 0
        tr.code = t->code;
        // t->flags = 0
        tr.flags = t->flags;
        
        // 此时 t->from 为 NULL,if 不命中
        if (t->from)
        {
            ......
        }
        else
        {
            tr.sender_pid = 0;
        }
        // 将 binder_transaction 结构体(t)拷贝到 binder_transaction_data 结构体(tr)
        tr.data_size = t->buffer->data_size;
        tr.offsets_size = t->buffer->offsets_size;
        tr.data.ptr.buffer = (binder_uintptr_t)((uintptr_t)t->buffer->data + proc->user_buffer_offset);
        tr.data.ptr.offsets = tr.data.ptr.buffer + ALIGN(t->buffer->data_size, sizeof(void *));
        
        // 将指令 BR_REPLY 拷贝到用户空间(mIn)
        if (put_user(cmd, (uint32_t __user *)ptr))
            return -EFAULT;
        // 指针后移
        ptr += sizeof(uint32_t);
        
        // 将描述数据的 tr 结构体拷贝到用户空间(mIn)
        if (copy_to_user(ptr, &tr, sizeof(tr)))
            return -EFAULT;
        // 指针后移
        ptr += sizeof(tr);
        ......
        // 此时 if 不命中
        if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY))
        {
            ......
        }
        else
        {
            t->buffer->transaction = NULL;
            // 释放内存
            kfree(t);
        }
        // 跳出循环
        break;
        ......
    }
    *consumed = ptr - buffer;
    ......
    return 0;
}
复制代码

binder_thread_read 函数执行完成返回后,一直返回到 IPCThreadState#waitForResponse 函数,继续执行。

// android\frameworks\native\libs\binder\IPCThreadState.cpp
status_t IPCThreadState::waitForResponse(
                    Parcel *reply, // reply 就是 ServiceManagerProxy#addSevice 中传入的 reply
                    status_t *acquireResult
){
    uint32_t cmd;
    int32_t err;
    // 循环等待结果
    while (1)
    {
        ......
        // 读取 mIn 中的指令(BR_REPLY)
        cmd = (uint32_t)mIn.readInt32();
        ......
        switch(cmd)
        {
            ......
            case BR_REPLY:
            {
                binder_transaction_data tr;
                // 取出 mIn 中的 binder_transaction_data 结构体
                err = mIn.read(&tr, sizeof(tr));
                ......
                // reply 不为空,if 命中
                if (reply)
                {
                    if ((tr.flags & TF_STATUS_CODE) == 0)
                    {
                        // 将 mIn 中描述的数据写入 reply 中
                        reply->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, this);
                    }
                    else
                    {
                        ......
                    }
                }
                else
                {
                    ......
                }
            }
            // 跳出循环
            goto finish;
            ......
        }
    }
finish:
    if (err != NO_ERROR)
    {
        if (acquireResult) *acquireResult = err;
        if (reply) reply->setError(err);
        mLastError = err;
    }
    return err;
}
复制代码

IPCThreadState#waitForResponse 函数执行完成返回后,一直返回到 ServiceManagerProxy#addSevice 函数。到此,AMS 的注册流程结束。

总结

按照指令的顺序,AMS 的注册流程大致如下图

未命名文件.png

大家结合这个流程图来看代码流程会更加清晰。

AMS 注册流程在 Binder IPC 机制中只算是冰山一角,但是借助跟踪 AMS 注册流程我们可以更加清晰的看到 Binder IPC 机制是如何运行的,这对于我们理解 Binder IPC 机制是很有帮助的。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享