Binder通信数据和流程分析

400 阅读17分钟

用户空间与驱动之间的数据交换

每个binder线程维护两个缓冲区 mOut 和 mIn,用于用户空间与驱动之间的数据交换。mOut 维护用户空间向驱动写入的数据,mIn 维护用户空间接受驱动写入的数据。

mOut 和 mIn 是 Parcel 类型,内部存入的数据为 cmd(通信协议)、binder_transaction_data(通信数据)。

通信数据内容如下:

struct binder_transaction_data {
  // 只用于 bcTRANSACTION(客户端->驱动) and brTRANSACTION(驱动->服务端),表明通信的目标
	union {
		size_t	handle;	/* binder_ref 的句柄值 desc,bcTRANSACTION 时有效  */
		void	*ptr;	/* 服务端引用计数 weakref_type 的地址,brTRANSACTION 时有效 */
	} target;
	void		*cookie;	/* 服务端 BBinder 对象的地址,brTRANSACTION 时有效 */
	unsigned int	code;		/* 通信协议码 */

	/* General information about the transaction. */
	unsigned int	flags;          // oneway等
	pid_t		sender_pid;
	uid_t		sender_euid;
	size_t		data_size;	/* 通信数据的字节大小 */
	size_t		offsets_size;	/* flat_binder_object 偏移数组的字节大小 */

  // 如果传输的是服务的通信数据,则要保存数据的地址和数组中 flat_binder_object 偏移数组的地址
	union {
		struct {
			/* 通信数据的地址 */
			const void	*buffer; 
			/* flat_binder_object 偏移数组的地址 */
			const void	*offsets;
		} ptr;
		uint8_t	buf[8];
	} data;
};

数据类型 binder_write_read 描述两个缓冲区(数据大小、地址)和驱动对其的消费情况。用户空间在使用系统调用 ioctl() 时传入binder_write_read对象,驱动根据 write_size 判断是否需要处理用户空间写入数据的数据(请求)和根据 read_size 判断用户空间是否接受驱动写入数据(响应)。驱动在处理完数据(write_buffer,read_buffer)后修改这个对象的 write_consumed 和 read_consumed 字段,并写回用户空间。用户空间以此决定是否清空之前写入的数据、处理驱动写入的数据。

// kernel, drivers/staging/android/binder.h
struct binder_write_read {
	signed long	write_size;	/* 表示用户空间已写入的字节数,驱动以此判断是否需要读取 */
	signed long	write_consumed;	/* 表示驱动已消费的字节数,用户空间以此判断是否清空缓冲区 */
	unsigned long	write_buffer;   /* 表示用户空间写入的缓冲区地址*/
	signed long	read_size;	/* 表示用户空间可以读入的字节数,驱动以此判断是否需要写入数据 */
	signed long	read_consumed;	/* 表示驱动已写入的字节数,用户空间以此判断是否有数据要处理 */
	unsigned long	read_buffer;    /* 表示驱动写入的缓冲区的地址*/
};

用户空间流程

服务端调用链:

joinThreadPool()
    getAndExecuteCommand()
        talkWithDriver()
        executeCommand()
            // case BR_TRANSACTION:
            // transact() -> onTransact() 服务端响应,调用具体的业务方法
            // sendReply();               服务端把结果返回客户端
                // writeTransactionData()
                // waitForResponse()

客户端调用链

transact()                    // 客户端调用代理对象的业务方法进入这里
    writeTransactionData()
    waitForResponse()
        talkWithDriver()        
        // case BR_REPLY:    // handle response data; 
        // ...

把请求数据写入缓冲区 mOut;

  1. 创建 binder_transaction_data 对象;
  2. 把目标(handle)、flags、服务方法code及参数(data)等写入 binder_transaction_data 对象;
  3. 把通信协议(cmd)和通信数据(binder_transaction_data)写入 mOut 缓冲区;
// IPCThreadState.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; /* Don't pass uninitialized stack data to a remote process */
    tr.target.handle = handle;   // binder_ref 的句柄值 desc
    tr.code = code;              // 自定义的服务code,对应具体的方法
    tr.flags = binderFlags;      // one_way 等
    tr.cookie = 0;
    tr.sender_pid = 0;
    tr.sender_euid = 0;

    const status_t err = data.errorCheck();       // data 为服务方法的参数
    if (err == NO_ERROR) {        
        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(); // binder对象(flat_binder_object)的偏移数组
    }
    ...    
    // 通信协议和通信数据写入 mOut 缓冲区
    mOut.writeInt32(cmd);
    mOut.write(&tr, sizeof(tr));

    return NO_ERROR;
}

与驱动交换数据

  1. 创建 transaction_write_binder 对象;
  2. 通过系统调用传入驱动;
  3. 根据驱动修改后的 transaction_write_binder 对象,清空 mOut 缓冲区、更新 mInt 中的 dataSize 和 dataPosition 从而在后面处理驱动返回的数据;
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
    if (mProcess->mDriverFD < 0) {
        return -EBADF;
    }

    binder_write_read bwr;

    // dataPosition 是读指针位置,这里表示已经读完驱动返回的数据了;需要再接受驱动的数据
    const bool needRead = mIn.dataPosition() >= mIn.dataSize();

    // mIn 缓冲区中的数据还没有处理完并且请求读取下一次数据,这时不写入数据
    const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
    
    // 描述写缓存信息
    bwr.write_size = outAvail;    // 表示向驱动写入数据的大小,等于 0 表示不向写入数据
    bwr.write_buffer = (uintptr_t)mOut.data();  // 写入数据的地址

    // 描述读缓冲信息
    if (doReceive && needRead) {
        bwr.read_size = mIn.dataCapacity();      // read_size 为 mIn 最大容量
        bwr.read_buffer = (uintptr_t)mIn.data(); // 地址为 mIn 中的 data 地址
    } else { // 不读入时,read_size 置为 0,表示本次不接受驱动返回数据
        bwr.read_size = 0;
        bwr.read_buffer = 0;
    }

    // Return immediately if there is nothing to do.
    if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;

    // 初始化 write_consumed,read_consumed,这两个值之后由驱动修改
    bwr.write_consumed = 0;
    bwr.read_consumed = 0;
    status_t err;
    do {
        // 通过系统调用于驱动通信,驱动处理后修改 binder_write_read 对象并写回用户空间
        if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
            err = NO_ERROR;
        else
            err = -errno;
        ...
    } while (err == -EINTR);

    if (err >= NO_ERROR) {
        // 驱动消费了数据
        if (bwr.write_consumed > 0) {
            if (bwr.write_consumed < mOut.dataSize())
                ...
            else { // 驱动消费了所有用户空间写入的数据, mOut 的 dataSize 置为 0
                mOut.setDataSize(0);
                processPostWriteDerefs();
            }
        }
        // 驱动返回了数据,设置 mIn 的 dataSize 和 dataPosition(读写指针位置), 
        // 在 waitForResponse 中处理驱动返回数据
        if (bwr.read_consumed > 0) {           
            mIn.setDataSize(bwr.read_consumed);
            mIn.setDataPosition(0);
        }
        return NO_ERROR;
    }
    return err;
}

处理驱动返回的数据 mIn

客户端

  1. 从缓冲区 mIn 中读取数据到 reply 中,作为代理端业务方法的返回值;
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
    uint32_t cmd;
    int32_t err;

    while (1) {
        if ((err=talkWithDriver()) < NO_ERROR) break;
        err = mIn.errorCheck();
        if (err < NO_ERROR) break;
        if (mIn.dataAvail() == 0) continue;

        cmd = (uint32_t)mIn.readInt32(); // 从缓冲区 mIn 读出协议码,根据协议码做不同的处理
        switch (cmd) {
        ...
        case BR_TRANSACTION_COMPLETE: // binder 驱动收到了 请求数据
            if (!reply && !acquireResult) goto finish;
            break; // 继续等待服务端返回
        ...
        case BR_REPLY: // 客户端收到了返回数据
            {
                binder_transaction_data tr;
                err = mIn.read(&tr, sizeof(tr)); // 从缓冲区 mIn 读数据到 tr 中
                if (err != NO_ERROR) goto finish;

                if (reply) { // 如果服务方法有返回值
                    if ((tr.flags & TF_STATUS_CODE) == 0) {
                        // 将 tr.data.ptr.buffer, tr.data_size, tr.data.ptr.offsets, tr.offsets_size
                        // 写入返回数据 reply 中
                        // freeBuffer 是函数对象,释放缓存
                        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);
                    } else {
                        // 错误处理、释放缓存
                        ...
                    }
                } else {
                    // 释放缓存
                    ...
                    continue;
                }
            }
            goto finish;

        default:
            err = executeCommand(cmd);
            if (err != NO_ERROR) goto finish;
            break;
        }
    }

finish:
    if (err != NO_ERROR) {
        if (acquireResult) *acquireResult = err;
        if (reply) reply->setError(err);
        mLastError = err;
        logExtendedError();
    }

    return err;
}

服务端

  1. 从缓冲区 mIn 中拷贝数据到 buffer, 作为业务方法的参数;
  2. 调用业务方法前增加强引用计数;
  3. 调用业务方法,并把结果写入 reply 中;
  4. 减少引用计数;

status_t IPCThreadState::executeCommand(int32_t cmd)
{
    BBinder* obj;
    RefBase::weakref_type* refs;
    status_t result = NO_ERROR;

    switch ((uint32_t)cmd) {
    ...
    // 增减引用计数相关
    case BR_ACQUIRE:
    case BR_RELEASE:
    case BR_INCREFS:
    case BR_DECREFS:
    case BR_ATTEMPT_ACQUIRE:
        break;
    // Binder 死亡通知相关
    case BR_DEAD_BINDER:
    case BR_CLEAR_DEATH_NOTIFICATION_DONE:
        break;
    case BR_TRANSACTION_SEC_CTX:
    case BR_TRANSACTION:  // 服务端收到驱动转发的客户端请求数据
        {
            binder_transaction_data_secctx tr_secctx;
            binder_transaction_data& tr = tr_secctx.transaction_data;

            if (cmd == (int) BR_TRANSACTION_SEC_CTX) {
                result = mIn.read(&tr_secctx, sizeof(tr_secctx));
            } else {
                result = mIn.read(&tr, sizeof(tr));  // 从缓冲区 mIn 读数据到 tr 中
                tr_secctx.secctx = 0;
            }
            ...            
            // tr 中的数据写入 buffer, 作为服务端服务方法的参数,并释放缓存
            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);
            ...
            Parcel reply;
            status_t error;
            if (tr.target.ptr) {
                // 调用服务方法前,先增加强引用
                if (reinterpret_cast<RefBase::weakref_type*>(
                        tr.target.ptr)->attemptIncStrong(this)) {
                    // cookie 为 BBinder 对象地址,类型转换后调用 BBinder::transact() -> onTransact();
                    // 服务中复写 onTransact(), 最终调用具体的业务方法,返回数据写入 reply
                    error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,
                            &reply, tr.flags);
                    // 服务完成后,减少引用计数
                    reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this);
                } else {
                    error = UNKNOWN_TRANSACTION;
                }

            } else {
                ...
            }
            ...
        }
        break;
        ...
    }
    ...
    return result;
}

驱动流程

用户空间通过系统调用 ioctl() 进入内核空间,对于 BINDER_WRITE_READ 类型的调用,在 binder_ioctl_write_read() 函数中处理。

  1. 首先把 binder_write_read 对象copy到内核空间;
  2. 其次,根据 write_size 和 read_size 处理用户空间的写和读请求;
  3. 最后,再修改 binder_write_read 后,写回用户空间;
binder_ioctl()
    binder_ioctl_write_read()    // case BINDER_WRITE_READ:
        copy_from_user()         // 把 binder_write_read 对象从用户空间copy到内核空间
        binder_thread_write()    // 处理用户空间写入的数据
            binder_transaction() // 生成 binder_work 和 binder_transaction,写入目标线程的任务队列
        binder_thread_read()     // 从任务队列中取出任务生成 binder_transaction_data,写入用户空间的缓冲区 mIn
        copy_to_user()           // 把 修改后的 binder_write_read 对象写回用户空间

binder_ioctl_write_read

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;
	unsigned int size = _IOC_SIZE(cmd);
	void __user *ubuf = (void __user *)arg;
	struct binder_write_read bwr;

        ...
  // 把 binder_write_read 对象从用户空间copy到内核空间
	if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {
		ret = -EFAULT;
		goto out;
	}
  // 用户空间有写入数据,binder_thread_write 处理
	if (bwr.write_size > 0) {
		ret = binder_thread_write(proc, thread,
					  bwr.write_buffer,
					  bwr.write_size,
					  &bwr.write_consumed);
		if (ret < 0) { // 错误处理,未消费数据
			bwr.read_consumed = 0;
			if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
				ret = -EFAULT;
			goto out;
		}
	}
  // 用户空间可以接受数据,binder_thread_read 处理
	if (bwr.read_size > 0) {
		ret = binder_thread_read(proc, thread, bwr.read_buffer,
					 bwr.read_size,
					 &bwr.read_consumed,
					 filp->f_flags & O_NONBLOCK);
		binder_inner_proc_lock(proc);
                // 唤醒线程
		if (!binder_worklist_empty_ilocked(&proc->todo))
			binder_wakeup_proc_ilocked(proc);
		binder_inner_proc_unlock(proc);
		if (ret < 0) { // 错误处理
			if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
				ret = -EFAULT;
			goto out;
		}
	}
        // 修改后的 binder_write_read 写回用户空间
	if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
		ret = -EFAULT;
		goto out;
	}
out:
	return ret;
}

binder_thread_write

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; // write_buffer 写入数据地址
	void __user *ptr = buffer + *consumed; // write_sonsumed 已消费字节数,ptr 读指针
	void __user *end = buffer + size;

	while (ptr < end && thread->return_error.cmd == BR_OK) {
		int ret;

		if (get_user(cmd, (uint32_t __user *)ptr)) // 从用户空间读取通信协议码cmd
			return -EFAULT;
		ptr += sizeof(uint32_t);                   // 更新读指针
		...
		switch (cmd) {
		// 引用计数相关
		case BC_INCREFS:
		case BC_ACQUIRE:
		case BC_RELEASE:
		case BC_DECREFS:
		case BC_INCREFS_DONE:
		case BC_ACQUIRE_DONE:
		case BC_ATTEMPT_ACQUIRE:
		case BC_ACQUIRE_RESULT:

		case BC_FREE_BUFFER:
		case BC_TRANSACTION_SG:
		case BC_REPLY_SG:
		// 用户空间向驱动写入的请求或响应数据
		case BC_TRANSACTION:
		case BC_REPLY: {
			struct binder_transaction_data tr;
			// // 从用户空间读取通信数据 binder_transaction_data,在 binder_transaction 处理
			if (copy_from_user(&tr, ptr, sizeof(tr)))
				return -EFAULT;
			ptr += sizeof(tr);
			binder_transaction(proc, thread, &tr,
					   cmd == BC_REPLY, 0);
			break;
		}
		// 服务端 Looper 相关
		case BC_REGISTER_LOOPER:
		case BC_ENTER_LOOPER:
		case BC_EXIT_LOOPER:
		// 死亡通知相关
		case BC_REQUEST_DEATH_NOTIFICATION:
		case BC_CLEAR_DEATH_NOTIFICATION:
		case BC_DEAD_BINDER_DONE:;

		*consumed = ptr - buffer; // 修改已消费写缓存数据大小,之后用户空间根据此清空写缓存 mOut
	}
	return 0;
}

binder_transaction

创建2个跨进程通信事务:BINDER_WORK_TRANSACTION, 插入目标线程,BINDER_WORK_TRANSACTION_COMPLETE,返回当前线程。

  1. 获取目标进程、线程信息;查找 binder_ref, binder_node;
  2. 生成跨进程通信数据 binder_transaction;
  3. 设置 binder_work 类型:目标线程和返回当前线程;
  4. 在目标进程的内存映射缓冲区分配内存,从发起进程的用户空间拷贝数据到目标进程的内存映射缓冲区;
  5. 把上述2个事务插入对应线程的目标队列,并唤醒目标线程。
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)
{
	int ret;
	struct binder_transaction *t;     // 跨进程通信数据
	struct binder_work *w;            // 
	struct binder_work *tcomplete;
	...
	// 目标进程、线程和 binder 实体对象
	struct binder_proc *target_proc = NULL;
	struct binder_thread *target_thread = NULL;
	struct binder_node *target_node = NULL;
	...
	const void __user *user_buffer = (const void __user *)
				(uintptr_t)tr->data.ptr.buffer;
	...
	// 获取目标线程、进程信息
	if (reply) { // BC_REPLY 服务端响应数据
		binder_inner_proc_lock(proc);
		...
		thread->transaction_stack = in_reply_to->to_parent;
		binder_inner_proc_unlock(proc);
		target_thread = binder_get_txn_from_and_acq_inner(in_reply_to);
		...
		binder_inner_proc_unlock(target_thread->proc);
	} else { // BC_TRANSACTION 客户端请求数据
                // 查找 binder_ref, binder_node
		if (tr->target.handle) {
			struct binder_ref *ref;
			// 之后要处理服务端响应数据,所以要确保 binder_ref 有强引用,不被回收
			binder_proc_lock(proc);
			// 通过 handle 在 binder_proc 的红黑树中查找 binder_ref, 
                        // true 表示同时对 binder_ref 增加强引用计数
			ref = binder_get_ref_olocked(proc, tr->target.handle,
						     true);
			// 通过 binder_ref 查找 binder_node
			if (ref) {
				target_node = binder_get_node_refs_for_txn(
						ref->node, &target_proc,
						&return_error);
			}
			binder_proc_unlock(proc);
		}
		...
	}

	// 为 binder_transaction *t 分配内存
	t = kzalloc(sizeof(*t), GFP_KERNEL);
	// ...
	// 为 binder_work *tcomplete 分配内存,// BINDER_WORK_TRANSACTION_COMPLETE
	tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);
	// ...

	// 填充跨进程通信数据 binder_transaction
	t->start_time = t_start_time;
	if (!reply && !(tr->flags & TF_ONE_WAY)) // BC_TRANSACTION, 非oneway-同步调用
		t->from = thread;
	else
		t->from = NULL;
	// 发起端信息
	t->from_pid = proc->pid;
	t->from_tid = thread->pid;
	t->sender_euid = task_euid(proc->tsk);
	// 目的端信息
	t->to_proc = target_proc;
	t->to_thread = target_thread;
	// 通信协议码
	t->code = tr->code;
	t->flags = tr->flags;
	t->is_nested = is_nested;
	// 设置目的线程优先级
	if (!(t->flags & TF_ONE_WAY) &&
	    binder_supported_policy(current->policy)) {
		/* Inherit supported policies for synchronous transactions */
		t->priority.sched_policy = current->policy;
		t->priority.prio = current->normal_prio;
	} else {
		/* Otherwise, fall back to the default priority */
		t->priority = target_proc->default_priority;
	}
	...
	// 在目标进程内存映射缓冲区分配内存
	t->buffer = binder_alloc_new_buf(&target_proc->alloc, tr->data_size,
		tr->offsets_size, extra_buffers_size,
		!reply && (t->flags & TF_ONE_WAY), current->tgid);
	...
	t->buffer->transaction = t;
	t->buffer->target_node = target_node;
	// 从发起进程的用户空间拷贝数据到目标进程的内存映射缓冲区
	if (binder_alloc_copy_user_to_buffer(
				&target_proc->alloc,
				t->buffer,
				ALIGN(tr->data_size, sizeof(void *)),
				(const void __user *)
					(uintptr_t)tr->data.ptr.offsets,
				tr->offsets_size)) {
		...
	}
	...
	// 设置 binder_work 类型
	if (t->buffer->oneway_spam_suspect)
		tcomplete->type = BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT;
	else
		tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
	t->work.type = BINDER_WORK_TRANSACTION;

	if (reply) { // BC_REPLY
                // tcomplete 插入当前线程
		binder_enqueue_thread_work(thread, tcomplete);
		binder_inner_proc_lock(target_proc);
		...
		// t 插入目标线程的任务队列
		binder_enqueue_thread_work_ilocked(target_thread, &t->work);
		binder_inner_proc_unlock(target_proc);
		// ...
		// 唤醒目标线程
		wake_up_interruptible_sync(&target_thread->wait);
		// 恢复服务端线程的优先级
		binder_restore_priority(thread, &in_reply_to->saved_priority);
		binder_free_transaction(in_reply_to);
	} else if (!(t->flags & TF_ONE_WAY)) { // BC_TRANSACTION 非oneway
		binder_inner_proc_lock(proc);
		// 把 BINDER_WORK_TRANSACTION_COMPLETE 延迟插入当前线程的任务队列;当服务端响应(BC_REPLY)返回时再处理
		binder_enqueue_deferred_thread_work_ilocked(thread, tcomplete);
		...
		binder_inner_proc_unlock(proc);
		// 把 BINDER_WORK_TRANSACTION 插入目标线程的任务队列,并唤醒目标线程
		return_error = binder_proc_transaction(t,
				target_proc, target_thread);
		...
	} else { // BC_TRANSACTION oneway
		...
	}
	//
	return;
	...
}

binder_thread_read

  1. 从当前线程或进程的todo任务队列取出任务 binder_work;
  2. 通过成员 binder_work 获取 binder_transaction 结构体地址;
  3. 填充 binder_transaction_data 对象,binder_transaction 中的数据写入 binder_transaction_data;
  4. 把通信协议码和通信数据写入用户空间缓冲区 mIn;

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; // read_buffer - mIn
	void __user *ptr = buffer + *consumed; // mIn 写指针
	void __user *end = buffer + size;

	int ret = 0;
	int wait_for_proc_work;
	...
retry:
	binder_inner_proc_lock(proc);
        // 用户空间进入到这里,阻塞;有任务插入队列时,被唤醒
	wait_for_proc_work = binder_available_for_proc_work_ilocked(thread);
        ...
	while (1) {
		uint32_t cmd;
		struct binder_transaction_data_secctx tr;
		struct binder_transaction_data *trd = &tr.transaction_data; // 写回用户空间的通信数据
		struct binder_work *w = NULL;   // 跨进程通信事务类型
		struct list_head *list = NULL;  // todo 队列
		struct binder_transaction *t = NULL; // 跨进程通信数据
		struct binder_thread *t_from;
		size_t trsize = sizeof(*trd);

		binder_inner_proc_lock(proc);

		if (list)
			goto skip;
		// 当前线程或进程的todo任务队列
		if (!binder_worklist_empty_ilocked(&thread->todo))
			list = &thread->todo;
		else if (!binder_worklist_empty_ilocked(&proc->todo) &&
			   wait_for_proc_work)
			list = &proc->todo;
		else {
			binder_inner_proc_unlock(proc);

			/* no data added */
			if (ptr - buffer == 4 && !thread->looper_need_return)
				goto retry;
			break;
		}
skip:
		if (end - ptr < sizeof(tr) + 4) {
			binder_inner_proc_unlock(proc);
			break;
		}
		// 从todo任务队列中取出任务 binder_work
		w = binder_dequeue_work_head_ilocked(list);
		//...
		// 根据 binder_work 的类型做不同的处理
		switch (w->type) {
		case BINDER_WORK_TRANSACTION: {
			// 通过成员 binder_work 获取 binder_transaction 结构体地址
			t = container_of(w, struct binder_transaction, work);
		} break;
		//...
		case BINDER_WORK_TRANSACTION_COMPLETE:
		case BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT: {
			if (proc->oneway_spam_detection_enabled &&
				   w->type == BINDER_WORK_TRANSACTION_ONEWAY_SPAM_SUSPECT)
				cmd = BR_ONEWAY_SPAM_SUSPECT;
			else // 返回协议码为 BR_TRANSACTION_COMPLETE
				cmd = BR_TRANSACTION_COMPLETE;
			binder_inner_proc_unlock(proc);
			kfree(w); // 释放 binder_work 对象
			// 把通信协议写入用户空间的缓冲区 mIn 
			if (put_user(cmd, (uint32_t __user *)ptr))
				return -EFAULT;
			ptr += sizeof(uint32_t); // 更新写指针位置
		} break;
		// binder_node 增加引用计数
		case BINDER_WORK_NODE:
		// 死亡通知
		case BINDER_WORK_DEAD_BINDER:
		case BINDER_WORK_DEAD_BINDER_AND_CLEAR:
		case BINDER_WORK_CLEAR_DEATH_NOTIFICATION:
		}

		// 下面为 BINDER_WORK_TRANSACTION 的逻辑
		if (!t)
			continue;

		if (t->buffer->target_node) { // target_node 不为空,表示这是服务端响应请求 - 返回协议
			struct binder_node *target_node = t->buffer->target_node;

			trd->target.ptr = target_node->ptr; // 服务端 weak_ref 
			trd->cookie =  target_node->cookie; // 服务端 BBinder
			binder_transaction_priority(thread, t, target_node); // 设置服务端线程优先级
			cmd = BR_TRANSACTION;   // 设置通信协议码
		} else {	// 客户端接受服务端的响应
			trd->target.ptr = 0;
			trd->cookie = 0;
			cmd = BR_REPLY;
		}
		trd->code = t->code;  // 通信协议
		trd->flags = t->flags;
		trd->sender_euid = from_kuid(current_user_ns(), t->sender_euid);
		// 设置进程id
		t_from = binder_get_txn_from(t);
		if (t_from) {
			struct task_struct *sender = t_from->proc->tsk;
			trd->sender_pid =
				task_tgid_nr_ns(sender,
						task_active_pid_ns(current));
		} else {
			trd->sender_pid = 0;
		}
		// ...
		// binder_transaction 中的数据写入 binder_transaction_data
		trd->data_size = t->buffer->data_size;
		trd->offsets_size = t->buffer->offsets_size;
		trd->data.ptr.buffer = (uintptr_t)t->buffer->user_data;
		trd->data.ptr.offsets = trd->data.ptr.buffer +
					ALIGN(t->buffer->data_size,
					    sizeof(void *));

		tr.secctx = t->security_ctx;
		if (t->security_ctx) {
			cmd = BR_TRANSACTION_SEC_CTX;
			trsize = sizeof(tr);
		}
		// 把通信协议码和数据写入用户空间
		if (put_user(cmd, (uint32_t __user *)ptr)) {
		}
		ptr += sizeof(uint32_t);
		if (copy_to_user(ptr, &tr, trsize)) {
		}
		ptr += trsize; // 更新写指针
		//...
		break;
	}

done:
	// ...
	return 0;
}

通信协议

通信协议分为2种:命令协议,用户空间向驱动写入,以BC_开头;返回协议,驱动向用户空间写入,以BR_开头;

事务类型:客户端-驱动-服务端,为 TRANSACTION;服务端-驱动-客户端,为 REPLY;

驱动收到用户空间的请求,返回的协议码以 COMPLETE 结尾;

命令协议

enum binder_driver_command_protocol {
	BC_TRANSACTION = _IOW('c', 0, struct binder_transaction_data), // 客户端请求
	BC_REPLY = _IOW('c', 1, struct binder_transaction_data),       // 服务端响应
        // 通信数据为 binder_transaction_data

	BC_ACQUIRE_RESULT = _IOW('c', 2, __s32),
	// 不支持

	BC_FREE_BUFFER = _IOW('c', 3, binder_uintptr_t),
	// 释放缓冲区

	BC_INCREFS = _IOW('c', 4, __u32), // 增加 binder_ref 的弱引用计数
	BC_ACQUIRE = _IOW('c', 5, __u32), // 增加 binder_ref 的强引用计数
	BC_RELEASE = _IOW('c', 6, __u32), // 减少 binder_ref 的强引用计数
	BC_DECREFS = _IOW('c', 7, __u32), // 减少 binder_ref 的弱引用计数
	// 通信数据为 binder_ref 的句柄值 desc

	BC_INCREFS_DONE = _IOW('c', 8, struct binder_ptr_cookie),
	BC_ACQUIRE_DONE = _IOW('c', 9, struct binder_ptr_cookie),
        // 成功增加 binder_node 强弱引用计数后

	BC_ATTEMPT_ACQUIRE = _IOW('c', 10, struct binder_pri_desc),
	// 不支持

	BC_REGISTER_LOOPER = _IO('c', 11),
	BC_ENTER_LOOPER = _IO('c', 12),
	BC_EXIT_LOOPER = _IO('c', 13),
        // 注册、进入、退出 binder 线程池

	BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14,
						struct binder_handle_cookie),
        // 发送 binder 死亡通知
	BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15,
						struct binder_handle_cookie),
        // 注销 binder 死亡通知
	BC_DEAD_BINDER_DONE = _IOW('c', 16, binder_uintptr_t),
        // 完成处理 binder 死亡通知

};

返回协议

enum binder_driver_return_protocol {
	BR_ERROR = _IOR('r', 0, __s32),
	// 驱动异常

	BR_OK = _IO('r', 1),
	// 驱动处理完成

	BR_TRANSACTION_SEC_CTX = _IOR('r', 2,
				      struct binder_transaction_data_secctx),
        // 设置 service manager

	BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data), // 驱动转发给服务端的请求
	BR_REPLY = _IOR('r', 3, struct binder_transaction_data),       // 驱动转发给客户端端的响应
	// 通信数据为 binder_transaction_data

	BR_ACQUIRE_RESULT = _IOR('r', 4, __s32),
	// 不支持

	BR_DEAD_REPLY = _IO('r', 5),
	// 目标进程或线程已经死亡

	BR_TRANSACTION_COMPLETE = _IO('r', 6),
	// 驱动收到用户空间发送的命令

	BR_INCREFS = _IOR('r', 7, struct binder_ptr_cookie),
	BR_ACQUIRE = _IOR('r', 8, struct binder_ptr_cookie),
	BR_RELEASE = _IOR('r', 9, struct binder_ptr_cookie),
	BR_DECREFS = _IOR('r', 10, struct binder_ptr_cookie),
	// 增加 service 的强弱引用计数

	BR_ATTEMPT_ACQUIRE = _IOR('r', 11, struct binder_pri_ptr_cookie),
	// 不支持

	BR_NOOP = _IO('r', 12),
	/*
	 * No parameters.  Do nothing and examine the next command.  It exists
	 * primarily so that we can replace it with a BR_SPAWN_LOOPER command.
	 */

	BR_SPAWN_LOOPER = _IO('r', 13),
	// 驱动通知进程增加 binder 线程

	BR_FINISHED = _IO('r', 14),
	// 不支持

	BR_DEAD_BINDER = _IOR('r', 15, binder_uintptr_t),
	// 通知客户端,服务端对象死亡
	BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, binder_uintptr_t),
	// 驱动完成注销死亡通知

	BR_FAILED_REPLY = _IO('r', 17),
	// 驱动处理 bcTRANSACTION or bcATTEMPT_ACQUIRE 发送异常

	BR_ONEWAY_SPAM_SUSPECT = _IO('r', 19),
	// 通知进程发送了太多的异常调用,缓冲区分配超过阈值
};