Binder—获取服务

获取服务

(1)Client 进程将进程间通信数据封装在 binder_write_read 中,用来传递给 Binder 驱动程序

Client 进程发送的进程间通信数据:目的进程 ServerManager + 服务名称(要访问的服务) + 要调用的函数:该函数返回服务句柄

(2)Client 进程向 Binder 驱动程序发送命令协议 BC_TRANSACTION,Binder 驱动程序根据协议内容(binder_transaction_data 封装的进程间通信数据)找到 ServiceManager 进程

  • Binder 驱动程序先立马向 Client 进程发送返回协议 BINDER_WORK_TRANSACTION_COMPLETE,表示 Client 进程的进程间通信请求已被接受,然后 Client 进程继续进入到 Binder 驱动程序中等待服务句柄返回
  • 唤醒 ServiceManager 进程,处理工作项(任务类型为 BINDER_WORK_TRANSACTION),从 Binder 驱动程序返回到用户空间 ServiceManager 进程,向 ServiceManager 进程发送返回协议 BR_TRANSACTION,执行对应函数

(3)ServiceManager 进程处理返回协议 BR_TRANSACTION,执行对应函数获取服务句柄
(4)ServiceManager 进程向 Binder 驱动程序发送命令协议 BC_REPLY,Binder 驱动程序根据在 ServiceManager 中所获取服务的句柄,然后在进程 Client 进程(获取服务进程)中创建 Binder 引用对象

  • Binder 驱动程序先立马向 ServiceManager 进程发送返回协议 BINDER_WORK_TRANSACTION_COMPLETE,表示返回的信息回复成功,处理后 ServiceManager 进程等待下一次 Binder 进程间通信请求
  • 向 Client 进程发送返回协议 BR_REPLY,从 Binder 驱动程序返回到用户空间 Client 进程,返回的数据:数据缓冲区中有一个 type 为 BINDER_TYPE_HANDLE 的 Binder 引用对象(其中句柄值 handle 由 Binder 驱动程序生成)

(5)Client 进程处理返回协议 BR_REPLY,获取返回的数据(包含了 Binder 引用对象的句柄值 handle)
至此,Client 进程便获取到了 Binder 引用对象的句柄值 handle

// ioctl -> binder_ioctl:Client 进程获取 Server 进程服务,该请求会经由 Binder 驱动程序转发给 ServerManager 进程处理

一、BC_TRANSACTION

Client 进程(获取服务的进程)发送命令协议 BC_TRANSACTION

binder_ioctl

[-> kernel/drivers/android/binder.c, binder_ioctl()]

// cmd = BINDER_WRITE_READ
// arg = &binder_write_read
static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
    int ret;
    // 取出 binder_open 中给 Client 进程创建的 binder_proc
    struct binder_roc *proc = filp->private_ata;
    struct binder_thread *thread;
    void __user *ubuf = (void __user *)arg;
    
    // 获取当前线程对应的 binder_thread
    thread = binder_get_thread(proc);
    
    // cmd = BINDER_WRITE_READ
    switch (cmd) {
    case BINDER_WRITE_READ: {
        struct binder_write_read bwr;
        // 拷贝从用户空间传来的 binder_write_read,保存到 bwr 变量
        if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {
            ret = -EFAULT;
            goto err;
        }

		// 拷贝的 bwr 中,只有 write_size 大于 0,write_buffer 用于向内核驱动发送数据
        if (bwr.write_size > 0) {
            ret = binder_thread_write(proc, thread, (void __user *)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 err;
            }
        }
        if (bwr.read_size > 0) {
            ret = binder_thread_read(proc, thread, (void __user *)bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK);
            if (!list_empty(&proc->todo))
                wake_up_interruptible(&proc->wait);
            if (ret < 0) {
                if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
                    ret = -EFAULT;
                goto err;
            }
        }
        
        if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
            ret = -EFAULT;
            goto err;
        }
		break;
	}
    default:
        ret = -EINVAL;
        goto err;
    }
    // 没有出错,则最终返回 0
    ret = 0;

err:
    if (thread)
        thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN;
	return ret;
}

[–>kernel/drivers/android/binder.c, 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;
    void __user *ptr = buffer + *consumed;
    void __user *end = buffer + size;
    
    while (ptr < end && thread->return_error == BR_OK) {
        // ptr 实际为 write_buffer,因此 cmd = BC_TRANSACTION
        if (get_user(cmd, (uint32_t __user *)ptr))
            return -EFAULT;
        ptr += sizeof(uint32_t);
        
        // 收到的通信数据:[BC_TRANSACTION + 内核缓冲区用户空间地址]
        switch (cmd) {
        case BC_TRANSACTION: // BC_TRANSACTION + 内核缓冲区用户空间地址
        case BC_REPLY: {
            struct binder_transaction_data tr;
            // 从用户空间拷贝 ptr(内核缓冲区用户空间地址)到内核空间
            if (copy_from_user(&tr, ptr, sizeof(tr)))
                return -EFAULT;
            ptr += sizeof(tr);
            binder_transaction(proc, thread, &tr, cmd == BC_REPLY); // 最后一个参数为 false
            break;
        }
        *consumed = ptr - buffer;
    }
    return 0;
}

[–>kernel/drivers/android/binder.c, binder_transaction()]

static void binder_transaction(struct binder_proc *proc, // 获取服务的进程
			       struct binder_thread *thread, // 获取服务的线程
			       struct binder_transaction_data *tr, int reply) // reply 为 false
{
    struct binder_transaction *t;
    struct binder_work *tcomplete;
    size_t *offp, *off_end;
    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;
    struct binder_transaction *in_reply_to = NULL;
    uint32_t return_error = BR_OK;
    
    if (reply) {
    	...
    } else { // reply 为 false,走这个
    	// tr->target.handle = 目的进程 ServerManager,值为 0
    	if (tr->target.handle) {
            struct binder_ref *ref;
            ref = binder_get_ref(proc, tr->target.handle);
            if (ref == NULL) {
                return_error = BR_FAILED_REPLY;
                goto err_invalid_target_handle;
            }
            target_node = ref->node;
        } else { // 走这个
        	// 给目标 target_node 赋值为 binder_context_mgr_node
            target_node = binder_context_mgr_node;
            if (target_node == NULL) {
                return_error = BR_DEAD_REPLY;
                goto err_no_context_mgr_node;
            }
        }
        e->to_node = target_node->debug_id;
        target_proc = target_node->proc; // ServiceManager 进程
        if (target_proc == NULL) {
            return_error = BR_DEAD_REPLY;
            goto err_dead_binder;
        }
        // 首次请求,获取服务的线程 thread 事务堆栈 transaction_stack 为空
        if (!(tr->flags & TF_ONE_WAY) && thread->transaction_stack) {
            struct binder_transaction *tmp;
            tmp = thread->transaction_stack;
            if (tmp->to_thread != thread) {
                return_error = BR_FAILED_REPLY;
                goto err_bad_call_stack;
            }
            while (tmp) {
                if (tmp->from && tmp->from->proc == target_proc)
                    target_thread = tmp->from;
                tmp = tmp->from_parent;
            }
        }
    }
    if (target_thread) {
        target_list = &target_thread->todo;
        target_wait = &target_thread->wait;
    } else { // 目标线程为空,走这个
    	// 获取目标进程 todo 队列
        target_list = &target_proc->todo;
        // 获取目标进程 wait 等待队列
        target_wait = &target_proc->wait;
    }
    
    // 创建 binder_transaction 结构体,用来记录一次单向传输过程
    t = kzalloc(sizeof(*t), GFP_KERNEL);
    if (t == NULL) {
        return_error = BR_FAILED_REPLY;
        goto err_alloc_t_failed;
    }
    binder_stats_created(BINDER_STAT_TRANSACTION);

    // 创建 binder_work 结构体
    tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);
    if (tcomplete == NULL) {
        return_error = BR_FAILED_REPLY;
        goto err_alloc_tcomplete_failed;
    }
    binder_stats_created(BINDER_STAT_TRANSACTION_COMPLETE);
    
    // 不是回复阶段 && 需要回复,当前是请求阶段,需要回复,
    if (!reply && !(tr->flags & TF_ONE_WAY))
        t->from = thread; // 获取服务的线程
    else
        t->from = NULL;
    
    t->sender_euid = proc->tsk->cred->euid;
    t->to_proc = target_proc; // ServiceManager 进程
    t->to_thread = target_thread; // 为 NULL
    t->code = tr->code;
    t->flags = tr->flags;
    t->priority = task_nice(current);
    t->buffer = binder_alloc_buf(target_proc, tr->data_size, tr->offsets_size, !reply && (t->flags & TF_ONE_WAY));
    if (t->buffer == NULL) {
        return_error = BR_FAILED_REPLY;
        goto err_binder_alloc_buf_failed;
    }
    t->buffer->allow_user_free = 0;
    t->buffer->debug_id = t->debug_id;
    t->buffer->transaction = t;
    t->buffer->target_node = target_node; // target_node 此时为空(请求阶段有值,回复阶段没有值)
    if (target_node)
        binder_inc_node(target_node, 1, 0, NULL);

    // offp:数据缓冲区起始位置
    offp = (size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *)));

    // 下面两个 if 从用户空间拷贝数据到内核空间
    // tr->data.ptr.buffer:binder_transaction_data 数据缓冲区中只包含要访问的服务名称
    if (copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) {
        return_error = BR_FAILED_REPLY;
        goto err_copy_data_failed;
    }
    // tr->data.ptr.offsets:binder_transaction_data 偏移数组记录了 Binder 对象在数据缓冲区中的位置(当前数据缓冲区中不含 Binder 对象)
    if (copy_from_user(offp, tr->data.ptr.offsets, tr->offsets_size)) {
        return_error = BR_FAILED_REPLY;
        goto err_copy_data_failed;
    }
    // offsets_size:偏移数组大小 
    off_end = (void *)offp + tr->offsets_size;
    // 当前数据缓冲区中不含 Binder 对象,跳过 for 循环(若有 Binder 对象时,则遍历数据缓冲区中的 Binder 对象,遍历范围 [offp, off_end])
    for (; offp < off_end; offp++) {
    	...
    }
    if (reply) {
        binder_pop_transaction(target_thread, in_reply_to);
    } else if (!(t->flags & TF_ONE_WAY)) { // 走这个
        t->need_reply = 1;
        t->from_parent = thread->transaction_stack; // from_parent 为 NULL
        // 此时才对获取服务的线程 thread 事务堆栈 transaction_stack 赋值,指向一个传输结构 t(binder_transaction 结构体)
        // 可以理解为将 t(binder_transaction 结构体)入栈(获取服务的线程 thread 事务堆栈),然后去做别的事情,做完后再把会得到处理
        thread->transaction_stack = t;
    } else {
        if (target_node->has_async_transaction) {
            target_list = &target_node->async_todo;
            target_wait = NULL;
        } else
            target_node->has_async_transaction = 1;
    }
    // 设置 t(binder_transaction 结构体)任务类型为 BINDER_WORK_TRANSACTION
    t->work.type = BINDER_WORK_TRANSACTION;
    // 将 t(binder_transaction 结构体)添加到目标线程 todo 队列 target_list 中
    list_add_tail(&t->work.entry, target_list);
    // 设置 tcomplete(binder_work 结构体)任务类型为 BINDER_WORK_TRANSACTION_COMPLETE
    tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
    // 将 tcomplete(binder_work 结构体)添加到获取服务的线程的 todo 队列 中
    list_add_tail(&tcomplete->entry, &thread->todo);
    // 目标进程 ServiceManager 处于睡眠中,此时唤醒目标进程 ServiceManager
    if (target_wait)
        wake_up_interruptible(target_wait);
    return;

...
}
  • binder_context_mgr_node 赋值时机
  • BINDER_WORK_TRANSACTION_COMPLETE:Binder 驱动程序先告诉 Client 进程发送的获取服务请求已被接受,然后 Client 进程继续进入到 Binder 驱动程序中等待请求结果
  • BINDER_WORK_TRANSACTION:目标进程 ServiceManager 要处理的工作项(任务类型为 BINDER_WORK_TRANSACTION)
  • 唤醒目标进程 ServiceManager

[–>kernel/drivers/android/binder.c, binder_thread_read()]

static int binder_thread_read(struct binder_proc *proc, // 目标进程 ServiceManager
                  struct binder_thread *thread, // 目标进程 ServiceManager 主线程
                  binder_uintptr_t binder_buffer, size_t size,
                  binder_size_t *consumed, int non_block)
{
    void __user *ptr = buffer + *consumed;
    void __user *end = buffer + size;

    int ret = 0;
    int wait_for_proc_work;

    if (*consumed == 0) {
        // 将 BR_NOOP 写回到用户空间
            // ptr = buffer + *consumed = bwr.read_buffer + bwr.consumed = bwr.read_buffer + 0 = bwr.read_buffer
        if (put_user(BR_NOOP, (uint32_t __user *)ptr))
            return -EFAULT;
        ptr += sizeof(uint32_t);
    }
    
    // while 循环用于处理进程或线程 todo 队列中存在的未处理工作项
    while (1) {
        uint32_t cmd;
        struct binder_transaction_data tr;
        struct binder_work *w;
        struct binder_transaction *t = NULL;
        
        if (!list_empty(&thread->todo))
            w = list_first_entry(&thread->todo, struct binder_work, entry);
        else if (!list_empty(&proc->todo) && wait_for_proc_work) // 当前目标进程 ServiceManager 的 todo 队列不为空
        	// 取出工作项 binder_work
            w = list_first_entry(&proc->todo, struct binder_work, entry);
        else {
            if (ptr - buffer == 4 && !(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN)) /* no data added */
                goto retry;
            break;
        }

        if (end - ptr < sizeof(tr) + 4)
            break;
        // 获取任务类型
        switch (w->type) {
        case BINDER_WORK_TRANSACTION: { // 唤醒后收到 BINDER_WORK_TRANSACTION
        	// 根据 binder_work 构造出 binder_transaction
            t = container_of(w, struct binder_transaction, work);
        } break;
        case BINDER_WORK_TRANSACTION_COMPLETE: { // 唤醒需要时间,因此先收到 BINDER_WORK_TRANSACTION_COMPLETE
            cmd = BR_TRANSACTION_COMPLETE;
            // 将 cmd = BR_TRANSACTION_COMPLETE 写回到用户空间
            if (put_user(cmd, (uint32_t __user *)ptr))
                return -EFAULT;
            ptr += sizeof(uint32_t);
            
            binder_stat_br(proc, thread, cmd);
            
            list_del(&w->entry);
            kfree(w);
            binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
        } break;
        }
        
        // 收到 BINDER_WORK_TRANSACTION 时,t 不为空
        if (!t)
            continue;
        
        // 请求阶段 target_node 不为空(请求阶段有值,回复阶段没有值),当前为 binder_context_mgr_node
        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;
            t->saved_priority = task_nice(current);
            if (t->priority < target_node->min_priority && !(t->flags & TF_ONE_WAY))
                binder_set_nice(t->priority);
            else if (!(t->flags & TF_ONE_WAY) || t->saved_priority > target_node->min_priority)
                binder_set_nice(target_node->min_priority);
            cmd = BR_TRANSACTION; // BR_TRANSACTION
        } else {
            tr.target.ptr = NULL;
            tr.cookie = NULL;
            cmd = BR_REPLY;
        }
        tr.code = t->code;
        tr.flags = t->flags;
        tr.sender_euid = t->sender_euid;

        if (t->from) {
            struct task_struct *sender = t->from->proc->tsk;
            tr.sender_pid = task_tgid_nr_ns(sender, current->nsproxy->pid_ns);
        } else {
            tr.sender_pid = 0;
        }

        tr.data_size = t->buffer->data_size;
        tr.offsets_size = t->buffer->offsets_size;
        // tr(binder_transaction_data)数据缓冲区中只包含要访问的服务名称
        tr.data.ptr.buffer = (void *)t->buffer->data + proc->user_buffer_offset;
        tr.data.ptr.offsets = tr.data.ptr.buffer + ALIGN(t->buffer->data_size, sizeof(void *));

        // 将 cmd = BR_TRANSACTION 写回到用户空间
        if (put_user(cmd, (uint32_t __user *)ptr))
            return -EFAULT;
        ptr += sizeof(uint32_t);
        // 将 tr(binder_transaction_data,数据缓冲区中只包含要访问的服务名称)写回到用户空间
        if (copy_to_user(ptr, &tr, sizeof(tr)))
            return -EFAULT;
        ptr += sizeof(tr);

        binder_stat_br(proc, thread, cmd);

        list_del(&t->work.entry);
        t->buffer->allow_user_free = 1;
        // 当前是 BR_TRANSACTION && 需要回复
        if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY)) {
            t->to_parent = thread->transaction_stack; // to_parent 为 NULL
            t->to_thread = thread;
            // 将 t(binder_transaction 结构体)入栈(ServiceManager 进程主线程事务堆栈)
            thread->transaction_stack = t;
        } else {
            t->buffer->transaction = NULL;
            kfree(t);
            binder_stats_deleted(BINDER_STAT_TRANSACTION);
        }
        break;
    }

done:
    *consumed = ptr - buffer;
    if (proc->requested_threads + proc->ready_threads == 0 && // 正在请求的次数 + 空闲线程数 = 0,即两个都为 0
        proc->requested_threads_started < proc->max_threads && // 已创建的线程数 < 最大线程数(该值在 ProcessState.cpp 的 open_driver 中设置为 15)
        (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED))) { // 当前线程是一个 Binder 线程(已注册成为 Binder 线程)
        proc->requested_threads++; // requested_threads + 1,则 if 条件不满足,一次只能增加一个线程,当线程增加成功后,驱动程序会将 requested_threads 会减一
        // 将返回协议 BR_SPAWN_LOOPER 写入到用户空间缓冲区 buffer,请求进程 proc 创建一个新的线程加入到 Binder 线程池中
        if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer))
            return -EFAULT;
    }
    // 返回
    return 0;
}
  • container_of:根据 binder_work 构造出 binder_transaction // 根据结构体成员地址计算结构体地址
  • ServiceManager 进程的主线程有待处理的工作项,会在 Binder 驱动程序的 binder_thread_read 中被唤醒,binder_parse 会根据收到的返回协议对工作项进行相应处理

二、BR_TRANSACTION

[–>binder.c, binder_parse()]

// func = svcmgr_handler
int binder_parse(struct binder_state *bs, struct binder_io *bio,
                 uintptr_t ptr, size_t size, binder_handler func)
{
    int r = 1;
    uintptr_t end = ptr + (uintptr_t) size;

    while (ptr < end) {
        uint32_t cmd = *(uint32_t *) ptr;
        ptr += sizeof(uint32_t);
        switch(cmd) {
        case BR_NOOP: // 首先收到上面在 binder_thread_read 中 put_user 过来的 BR_NOOP(睡眠之前已收到)
            break; // 返回
        case BR_TRANSACTION: { // 处理驱动程序转发的请求(唤醒之后才收到)
            struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr; // binder_transaction_data 用于描述进程间通信过程中传输的数据
            // func = svcmgr_handler
            if (func) {
                unsigned rdata[256/4];
                struct binder_io msg;
                struct binder_io reply;
                int res;
                
                // 初始化 reply(将进程间通信结果数据保存到缓冲区 rdata 中),用于回复数据给 Binder 驱动程序
                bio_init(&reply, rdata, sizeof(rdata), 4);
                // 初始化 msg(解析并保存从 Binder 驱动程序中读取到的进程间通信数据服务名称),此时 msg 中包含服务名称
                    // 解析数据,将 txn(binder_transaction_data)转为 msg(binder_io)
                bio_init_from_txn(&msg, txn);
                // 调用函数 svcmgr_handler 处理 BR_TRANSACTION,并将结果保存在 reply 中
                res = func(bs, txn, &msg, &reply);
                // 回复结果 reply 给 Binder 驱动程序
                binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
            }
            ptr += sizeof(*txn);
            break;
        }
        case BR_REPLY: {
            struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
            if (bio) {
                bio_init_from_txn(bio, txn);
                bio = 0;
            }
            ptr += sizeof(*txn);
            r = 0;
            break;
        }
        default:
            return -1;
        }
    }

    return r;
}

[–>service_manager.c, svcmgr_handler()]

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;
    
    strict_policy = bio_get_uint32(msg);
    s = bio_get_string16(msg, &len);
    if (s == NULL) {
        return -1;
    }
    
    if ((len != (sizeof(svcmgr_id) / 2)) || memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
        return -1;
    }

    switch(txn->code) {
    // 获取服务
    case SVC_MGR_GET_SERVICE:
    case SVC_MGR_CHECK_SERVICE:
    	// 服务名称
        s = bio_get_string16(msg, &len);
        if (s == NULL) {
            return -1;
        }
        // 根据服务名称查找相应服务句柄
        handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid);
        if (!handle)
            break;
        // 把服务句柄封装成一个 Binder 对象(type = BINDER_TYPE_HANDLE)
        bio_put_ref(reply, handle);
        // 返回 0
        return 0;
    default:
        return -1;
    }

    // 操作成功(把 00 00 00 00 作为 reply(binder_io)data,表示操作成功),之后会通过 Binder 驱动程序返回给 Client 进程
    bio_put_uint32(reply, 0);
    return 0;
}

[–>service_manager.c, do_find_service()]
根据服务名称,从链表 svcinfo 中查找,若存在则返回服务对应的句柄值

uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid)
{
    struct svcinfo *si;
    
    // 服务是否满足查询条件
    if (!svc_can_find(s, len, spid)) {
        return 0;
    }
    // 查询相应的服务
    si = find_svc(s, len);

    if (si && si->handle) {
        if (!si->allow_isolated) {
            // 如果此服务不允许从独立进程进行访问,请检查 uid 是否已隔离
            uid_t appid = uid % AID_USER;
            // 检查该服务是否允许独立于进程而单独存在
            if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
                return 0;
            }
            // 返回服务对应的句柄
            return si->handle;
        }
    } else {
        return 0;
    }
}

[–>binder.c, bio_put_ref()]
把根据服务名称获取的服务句柄值,封装成一个类型为 BINDER_TYPE_HANDLE 的 Binder 引用对象

void bio_put_ref(struct binder_io *bio, uint32_t handle)
{
    struct flat_binder_object *obj;

    if (handle)
        // 从 bio(binder_io)的数据缓冲区中分配一个 obj(flat_binder_object)
        obj = bio_alloc_obj(bio);
    else
        obj = bio_alloc(bio, sizeof(*obj));

    if (!obj)
        return;

    // 对 obj(flat_binder_object)进行初始化
    obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
    obj->type = BINDER_TYPE_HANDLE; // 设置 obj(flat_binder_object)描述的 Binder 对象类型为 BINDER_TYPE_HANDLE,表明是一个 Binder 引用对象
    obj->handle = handle; // 设置 obj(flat_binder_object)描述的 Binder 对象句柄值为 handle
    obj->cookie = 0;
}

[–>binder.c, binder_send_reply()]
把封装有服务句柄值的 reply(binder_io)封装到 binder_transaction_data 中

void binder_send_reply(struct binder_state *bs,
                       struct binder_io *reply, // 写给 Binder 驱动程序的数据
                       binder_uintptr_t buffer_to_free,
                       int 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;
    data.buffer = buffer_to_free; // BC_FREE_BUFFER 后面跟的通信数据是内核缓冲区用户空间地址
    data.cmd_reply = BC_REPLY;
    data.txn.target.ptr = 0; // BC_REPLY 后面跟的通信数据是 binder_transaction_data
    data.txn.cookie = 0;
    data.txn.code = 0;
    if (status) {
        data.txn.flags = TF_STATUS_CODE;
        data.txn.data_size = sizeof(int);
        data.txn.offsets_size = 0;
        data.txn.data.ptr.buffer = (uintptr_t)&status;
        data.txn.data.ptr.offsets = 0;
    } else { // 正常走这个
        // 将 reply(binder_io)数据缓冲区和偏移数组设置到匿名结构体 data 中(主要成员 binder_transaction_data)
        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; // 数据缓冲区中有一个 type 为 BINDER_TYPE_HANDLE 的 Binder 对象
        data.txn.data.ptr.offsets = (uintptr_t)reply->offs0; // 偏移数组记录了 Binder 对象在数据缓冲区中的位置
    }
    // 将命令协议 BC_FREE_BUFFER 和 BC_REPLY 发送给 Binder 驱动程序
    binder_write(bs, &data, sizeof(data));
}

三、BC_REPLY

[–>binder.c, binder_write()]
调用 ioctl(),将封装有服务句柄值的 binder_transaction_data 发送给 Binder 驱动程序

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;
    // 通过 IO 控制命令 BINDER_WRITE_READ 将命令协议 BC_FREE_BUFFER 和 BC_REPLY 发送给 Binder 驱动程序
        // write_size 大于 0,read_size 等于 0,只写不读,写完立马返回 ServiceManager 用户空间
    res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
    return res;
}

通过 ioctl() 将 binder_write_read 数据发给 Binder 驱动,调用 binder_ioctl() 方法,write_size 大于 0,read_size 等于 0,调用的是 binder_thread_write

[–>kernel/drivers/android/binder.c, binder_thread_write()]

static int binder_thread_write(struct binder_proc *proc, //  ServiceManager 进程
            struct binder_thread *thread, //  ServiceManager 进程主线程
            binder_uintptr_t binder_buffer, size_t size,
            binder_size_t *consumed)
{
    uint32_t cmd;
    void __user *ptr = buffer + *consumed;
    void __user *end = buffer + size;
    
    while (ptr < end && thread->return_error == BR_OK) {
        // ptr 实际为 write_buffer,因此 cmd = BC_FREE_BUFFER + BC_REPLY
        if (get_user(cmd, (uint32_t __user *)ptr))
            return -EFAULT;
        ptr += sizeof(uint32_t);
        
        // 收到的通信数据:[BC_FREE_BUFFER + 内核缓冲区用户空间地址]+ [BC_REPLY + binder_transaction_data]
        switch (cmd) {
        case BC_FREE_BUFFER: { // BC_FREE_BUFFER + 内核缓冲区用户空间地址
            void __user *data_ptr;
            struct binder_buffer *buffer;
            
            if (get_user(data_ptr, (void * __user *)ptr))
            return -EFAULT;
            ptr += sizeof(void *);
            
            buffer = binder_buffer_lookup(proc, data_ptr);
            
            if (buffer->transaction) {
                buffer->transaction->buffer = NULL;
                buffer->transaction = NULL;
            }
            if (buffer->async_transaction && buffer->target_node) {
                if (list_empty(&buffer->target_node->async_todo))
                    buffer->target_node->has_async_transaction = 0;
                else
                    list_move_tail(buffer->target_node->async_todo.next, &thread->todo);
            }
            binder_transaction_buffer_release(proc, buffer, NULL);
            binder_free_buf(proc, buffer);
            break;
        }
        case BC_TRANSACTION:
        case BC_REPLY: { // BC_REPLY + binder_transaction_data
            struct binder_transaction_data tr;
            // 从用户空间拷贝 ptr(包含 BC_REPLY + binder_transaction_data)到内核空间,转为 binder_transaction_data
            if (copy_from_user(&tr, ptr, sizeof(tr)))
                return -EFAULT;
            ptr += sizeof(tr);
            binder_transaction(proc, thread, &tr, cmd == BC_REPLY); // 最后一个参数为 true
            break;
        }
        *consumed = ptr - buffer;
    }
    return 0;
}

[–>kernel/drivers/android/binder.c, binder_transaction()]
Binder 驱动程序为获取服务的进程创建 Binder 实体对象对应的 Binder 引用对象

static void binder_transaction(struct binder_proc *proc, // ServiceManager 进程
			       struct binder_thread *thread, //  ServiceManager 进程主线程
			       struct binder_transaction_data *tr, int reply) // reply 为 true
{
    struct binder_transaction *t;
    struct binder_work *tcomplete;
    size_t *offp, *off_end;
    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;
    struct binder_transaction *in_reply_to = NULL;
    uint32_t return_error = BR_OK;
    
    if (reply) { // reply 为 true,走这个
    	// 从 ServiceManager 进程主线程任务堆栈取出栈顶对象 binder_transaction
        in_reply_to = thread->transaction_stack;
        if (in_reply_to == NULL) {
            return_error = BR_FAILED_REPLY;
            goto err_empty_call_stack;
        }
        // 恢复目标线程优先级(之前 Binder 驱动程序分发进程间通信请求交给线程处理时,将处理线程优先级设置成发起请求线程优先级,现请求已处理完成,线程优先级需要恢复)
        binder_set_nice(in_reply_to->saved_priority);
        if (in_reply_to->to_thread != thread) {
            return_error = BR_FAILED_REPLY;
            in_reply_to = NULL;
            goto err_bad_call_stack;
        }
        // 出栈:thread(ServiceManager 进程主线程)事务堆栈指向 NULL
        	// 此次出栈是从 thread(ServiceManager 进程主线程)事务堆栈中出栈
        thread->transaction_stack = in_reply_to->to_parent;
        // target_thread:与 thread(ServiceManager 进程主线程)通信的线程,发起请求获取服务句柄的线程
        target_thread = in_reply_to->from;
        if (target_thread == NULL) {
            return_error = BR_DEAD_REPLY;
            goto err_dead_binder;
        }
        if (target_thread->transaction_stack != in_reply_to) {
            return_error = BR_FAILED_REPLY;
            in_reply_to = NULL;
            target_thread = NULL;
            goto err_dead_binder;
        }
        // target_proc:获取服务的进程(找到了要回复的进程)
        target_proc = target_thread->proc;
    } else {
        ...
    }
    if (target_thread) { // 目标线程不为空,走这个
        // 获取目标线程 todo 队列
        target_list = &target_thread->todo;
        // 获取目标线程 wait 等待队列
        target_wait = &target_thread->wait;
    } else {
        target_list = &target_proc->todo;
        target_wait = &target_proc->wait;
    }
    
    // 创建 binder_transaction 结构体
    t = kzalloc(sizeof(*t), GFP_KERNEL);
    if (t == NULL) {
        return_error = BR_FAILED_REPLY;
        goto err_alloc_t_failed;
    }
    binder_stats_created(BINDER_STAT_TRANSACTION);

    // 创建 binder_work 结构体
    tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);
    if (tcomplete == NULL) {
        return_error = BR_FAILED_REPLY;
        goto err_alloc_tcomplete_failed;
    }
    binder_stats_created(BINDER_STAT_TRANSACTION_COMPLETE);
    
    if (!reply && !(tr->flags & TF_ONE_WAY))
        t->from = thread;
    else
        t->from = NULL;
    
    t->sender_euid = proc->tsk->cred->euid;
    t->to_proc = target_proc;
    t->to_thread = target_thread;
    t->code = tr->code;
    t->flags = tr->flags;
    t->priority = task_nice(current);
    // 给 target_proc(获取服务的进程)在内核空间划一块地方,用来保存从用户空间拷贝来的数据
    // 这里体现了 Binder 一次拷贝的原理,下面会从 ServiceManager 进程的用户空间数据直接拷贝到目标进程 target_proc(获取服务的进程)的内核空间,而 Binder 内核空间的数据能直接映射到用户空间,也就不再需要拷贝到目标进程的用户空间
    t->buffer = binder_alloc_buf(target_proc, tr->data_size, tr->offsets_size, !reply && (t->flags & TF_ONE_WAY));
    if (t->buffer == NULL) {
        return_error = BR_FAILED_REPLY;
        goto err_binder_alloc_buf_failed;
    }
    t->buffer->allow_user_free = 0;
    t->buffer->debug_id = t->debug_id;
    t->buffer->transaction = t;
    t->buffer->target_node = target_node; // target_node 此时为空(请求阶段有值,回复阶段没有值)
    if (target_node)
        binder_inc_node(target_node, 1, 0, NULL);

    // offp:数据缓冲区起始地址
    offp = (size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *)));

    // 下面两个 if 从 ServiceManager 进程的用户空间拷贝数据到目标进程 target_proc(获取服务的进程)的内核空间
    	// t->buffer:给 target_proc(获取服务的进程)在内核空间划分的空间
    	// tr->data.ptr.buffer:binder_transaction_data 数据缓冲区中有一个 type 为 BINDER_TYPE_HANDLE 的 Binder 对象
    if (copy_from_user(t->buffer->data, tr->data.ptr.buffer, tr->data_size)) {
        return_error = BR_FAILED_REPLY;
        goto err_copy_data_failed;
    }
    // tr->data.ptr.offsets:binder_transaction_data 偏移数组记录了 Binder 对象在数据缓冲区中的位置
    if (copy_from_user(offp, tr->data.ptr.offsets, tr->offsets_size)) {
        return_error = BR_FAILED_REPLY;
        goto err_copy_data_failed;
    }
    // offsets_size:偏移数组大小 
    off_end = (void *)offp + tr->offsets_size;
    // for 循环遍历数据缓冲区中的 Binder 对象,遍历范围 [offp, off_end]
    for (; offp < off_end; offp++) {
        struct flat_binder_object *fp;
        // 根据数据缓冲区起始位置 + 偏移确定一个 Binder 对象,赋给 fp(flat_binder_object)
        fp = (struct flat_binder_object *)(t->buffer->data + *offp);
        switch (fp->type) {
        case BINDER_TYPE_HANDLE: // BINDER_TYPE_HANDLE
        case BINDER_TYPE_WEAK_HANDLE: {
            // 根据 fp->handle(在 ServiceManager 中所获取服务的句柄)在进程 proc(ServiceManager)中找到 Binder 引用对象
            	// 这个 Binder 引用对象是 Binder 驱动程序在注册服务阶段为 ServiceManager 进程创建的
            struct binder_ref *ref = binder_get_ref(proc, fp->handle);
            if (ref == NULL) {
                return_error = BR_FAILED_REPLY;
                goto err_binder_get_ref_failed;
            }
            if (security_binder_transfer_binder(proc->tsk, target_proc->tsk)) {
                return_error = BR_FAILED_REPLY;
                goto err_binder_get_ref_failed;
            }
            // ref->node->proc:Binder 引用对象引用的 Binder 实体对象所在进程,即提供服务的进程
                // ref:Binder 引用对象
                // ref->node:Binder 引用对象引用的 Binder 实体对象
            // target_proc:获取服务的进程(Client)
            if (ref->node->proc == target_proc) {
                if (fp->type == BINDER_TYPE_HANDLE)
                    fp->type = BINDER_TYPE_BINDER;
                else
                    fp->type = BINDER_TYPE_WEAK_BINDER;
                fp->binder = ref->node->ptr;
                fp->cookie = ref->node->cookie;
                binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL);
            } else { // 提供服务的进程(ServiceManager)!= 获取服务的进程(Client),走这个
                struct binder_ref *new_ref;
                // 在 target_proc(获取服务的进程)中查找一个 Binder 引用对象(没有则创建),然后返回
                	// new_ref 是 Binder 驱动程序为获取服务的进程(Client)创建的 Binder 引用对象
                new_ref = binder_get_ref_for_node(target_proc, ref->node);
                if (new_ref == NULL) {
                    return_error = BR_FAILED_REPLY;
                    goto err_binder_get_ref_for_node_failed;
                }
                // 设置 fp->handle 为 Binder 引用对象 new_ref 的句柄值
                    // fp 和 t->buffer->data 有关,t 是 binder_transaction 结构体
                fp->handle = new_ref->desc;
                binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL);
            }
        } break;
        }
    }
    if (reply) {
    	// 出栈:target_thread(发起请求获取服务句柄的线程)事务堆栈指向自身的 from_parent = NULL
        	// 此次出栈是从 target_thread(发起请求获取服务句柄的线程)事务堆栈中出栈
        binder_pop_transaction(target_thread, in_reply_to);
    } else if (!(t->flags & TF_ONE_WAY)) {
        t->need_reply = 1;
        t->from_parent = thread->transaction_stack;
        thread->transaction_stack = t;
    } else {
        if (target_node->has_async_transaction) {
            target_list = &target_node->async_todo;
            target_wait = NULL;
        } else
            target_node->has_async_transaction = 1;
    }
    // 设置 t(binder_transaction 结构体)任务类型为 BINDER_WORK_TRANSACTION
    t->work.type = BINDER_WORK_TRANSACTION;
    // 将 t(binder_transaction 结构体)添加到目标线程 todo 队列 target_list 中
    list_add_tail(&t->work.entry, target_list);
    // 设置 tcomplete(binder_work 结构体)任务类型为 BINDER_WORK_TRANSACTION_COMPLETE
    tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
    // 将 tcomplete(binder_work 结构体)添加到 ServiceManager 进程主线程的 todo 队列 中
    list_add_tail(&tcomplete->entry, &thread->todo);
    // 目标进程(获取服务的进程)处于睡眠中,此时唤醒目标进程(获取服务的进程)
    if (target_wait)
        wake_up_interruptible(target_wait);
    return;

...
}
  • BINDER_WORK_TRANSACTION_COMPLETE:Binder 驱动程序先告诉 ServiceManager 进程返回的信息回复成功,处理后 ServiceManager 进程等待下一次 Binder 进程间通信请求
  • BINDER_WORK_TRANSACTION:目标线程 Client 要处理的工作项(任务类型为 BINDER_WORK_TRANSACTION)
  • 唤醒目标进程(获取服务的进程)

[–>kernel/drivers/android/binder.c, binder_get_ref_for_node()]

注册服务时,Binder 驱动程序会给 ServiceManager 进程创建 Binder 实体对象对应的 Binder 引用对象

获取服务时,Binder 驱动程序会根据服务句柄值查找服务注册时创建的 Binder 引用对象,接着找到 Binder 引用对象引用的 Binder 实体对象,然后为获取服务的进程创建一个 Binder 引用对象,并引用这个 Binder 实体对象,方法返回时返回该 Binder 引用对象

static struct binder_ref *binder_get_ref_for_node(struct binder_proc *proc, // 获取服务的进程
						  struct binder_node *node) // Binder 引用对象(这个是 Binder 驱动程序为 ServiceManager 进程创建的)引用的 Binder 实体对象
{
    struct rb_node *n;
    // proc->refs_by_node.rb_node:获取服务的进程中所有 Binder 引用对象组成的红黑树的根节点
        // proc:获取服务的进程
        // proc->refs_by_node:获取服务的进程中所有 Binder 引用对象组成的红黑树
    struct rb_node **p = &proc->refs_by_node.rb_node;
    struct rb_node *parent = NULL;
    struct binder_ref *ref, *new_ref;
    
    // 首次进入红黑树没有节点,跳过 while 循环
    // 遍历由获取服务的进程中所有 Binder 引用对象组成的红黑树 refs_by_node(节点 node 以 Binder 引用对象的 node 作为关键词),检查是否存在 Binder 实体对象对应的 Binder 引用对象
    while (*p) {
        parent = *p;
        ref = rb_entry(parent, struct binder_ref, rb_node_node);
        
        if (node < ref->node)
            p = &(*p)->rb_left;
        else if (node > ref->node)
            p = &(*p)->rb_right;
        else // else 对应 node == ref->node 的情况,即找到了 Binder 实体对象对应的 Binder 引用对象
            // 返回已存在的 Binder 引用对象
            return ref;
    }
    
    // 执行到这,说明获取服务的进程中所有 Binder 引用对象组成的红黑树上没有找到 Binder 实体对象对应的 Binder 引用对象
    // 创建一个 Binder 引用对象
    new_ref = kzalloc(sizeof(*ref), GFP_KERNEL);
    if (new_ref == NULL)
        return NULL;
    binder_stats_created(BINDER_STAT_REF);
    new_ref->debug_id = ++binder_last_id;
    // 设置 Binder 引用对象 new_ref 对应 proc 为获取服务的进程
    new_ref->proc = proc;
    // 设置 Binder 引用对象 new_ref 对应 node 为 Binder 实体对象
    new_ref->node = node;
    // 以 Binder 引用对象的 node 作为关键词把 Binder 引用对象挂到获取服务的进程的红黑树 refs_by_node 上
    rb_link_node(&new_ref->rb_node_node, parent, p);
    rb_insert_color(&new_ref->rb_node_node, &proc->refs_by_node);

    // 此时 node(Binder 引用对象引用的 Binder 实体对象)不是 ServiceManager 进程对应的 binder_context_mgr_node,设置 Binder 引用对象句柄值为 1
    new_ref->desc = (node == binder_context_mgr_node) ? 0 : 1;
    // 首次进入红黑树没有节点,跳过 for 循环
    // 遍历由获取服务的进程中所有 Binder 引用对象组成的红黑树 refs_by_desc(节点 node 以 Binder 引用对象的 desc 作为关键词)
    for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) {
        ref = rb_entry(n, struct binder_ref, rb_node_desc);
        // 遍历完红黑树上所有节点,此时 new_ref->desc 最终比红黑树节点总数大 1,跳出 for 循环
        if (ref->desc > new_ref->desc)
            break;
        // 更新 Binder 引用对象句柄值 new_ref->desc,每次加一
        new_ref->desc = ref->desc + 1;
    }

    // 获取服务的进程中所有 Binder 引用对象组成的红黑树的根节点
    p = &proc->refs_by_desc.rb_node;
    // 走到这是因为没有 Binder 实体对象对应的 Binder 引用对象,而后创建了 Binder 引用对象,在此需要
    // 遍历由获取服务的进程中所有 Binder 引用对象组成的红黑树 refs_by_desc(节点 node 以 Binder 引用对象的 desc 作为关键词),更新节点 p
    while (*p) {
        parent = *p;
        ref = rb_entry(parent, struct binder_ref, rb_node_desc);
        
        // new_ref 不在红黑树 refs_by_desc 上,不会走最下面的 else,只会走 if 和 else if,直至 *p 为 NULL(在红黑树上不为 NULL),跳出 while 循环
        if (new_ref->desc < ref->desc)
            p = &(*p)->rb_left;
        else if (new_ref->desc > ref->desc)
            p = &(*p)->rb_right;
        else
            BUG();
    }
    // 以 Binder 引用对象的 desc 作为关键词把 Binder 引用对象挂到获取服务的进程的红黑树 refs_by_desc 上
    rb_link_node(&new_ref->rb_node_desc, parent, p);
    rb_insert_color(&new_ref->rb_node_desc, &proc->refs_by_desc);
    if (node) {
        // 以 Binder 引用对象的 node_entry 为关键词把 Binder 引用对象添加到 Binder 实体对象引用链表中
            // node->refs:Binder 实体对象的 Binder 引用链表
        hlist_add_head(&new_ref->node_entry, &node->refs);
    }
    // 返回创建的 Binder 引用对象
    return new_ref;
}

[–>kernel/drivers/android/binder.c, binder_thread_read()]
获取服务的进程被唤醒后,处理进程或线程 todo 队列中存在的未处理工作项

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 *ptr = buffer + *consumed;
    void __user *end = buffer + size;

    int ret = 0;
    int wait_for_proc_work;

    if (*consumed == 0) {
        // 将 BR_NOOP 写回到用户空间
            // ptr = buffer + *consumed = bwr.read_buffer + bwr.consumed = bwr.read_buffer + 0 = bwr.read_buffer
        if (put_user(BR_NOOP, (uint32_t __user *)ptr))
            return -EFAULT;
        ptr += sizeof(uint32_t);
    }
    
retry:
    // 线程事务堆栈为空(没有等待其他线程完成事务) && 线程 todo 队列为空,此时可以去等待处理进程 todo 队列中的待处理项
    wait_for_proc_work = thread->transaction_stack == NULL && list_empty(&thread->todo);
    
    // 设置线程处于空闲状态
    thread->looper &= ~BINDER_LOOPER_STATE_WAITING;
    if (wait_for_proc_work)
        proc->ready_threads++;
    
    // 线程等待处理进程 todo 队列中可能存在的未处理工作项
    if (wait_for_proc_work) {
        if (!(thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED))) {
            wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
        }
        binder_set_nice(proc->default_priority);
        // non_block 表示不阻塞,没有可处理工作项时,不休眠立即返回
        if (non_block) {
            if (!binder_has_proc_work(proc, thread))
                ret = -EAGAIN;
        } else
            // 线程睡眠等待进程有待处理工作项
            ret = wait_event_interruptible_exclusive(proc->wait, binder_has_proc_work(proc, thread));
    } else { // 线程处理自己 todo 队列中可能存在的未处理工作项
        if (non_block) {
            if (!binder_has_thread_work(thread))
            ret = -EAGAIN;
        } else
            // 线程睡眠等待自己有待处理工作项
            ret = wait_event_interruptible(thread->wait, binder_has_thread_work(thread));
    }
    
    if (wait_for_proc_work)
        proc->ready_threads--;
    // 取消线程处于空闲状态
    thread->looper &= ~BINDER_LOOPER_STATE_WAITING;
    
    if (ret)
        return ret;
    
    // while 循环用于处理进程或线程 todo 队列中存在的未处理工作项
    while (1) {
        uint32_t cmd;
        struct binder_transaction_data tr;
        struct binder_work *w;
        struct binder_transaction *t = NULL;
        
        // 线程的 todo 队列不为空
        if (!list_empty(&thread->todo))
            // 取出任务
            w = list_first_entry(&thread->todo, struct binder_work, entry);
        else if (!list_empty(&proc->todo) && wait_for_proc_work)
            w = list_first_entry(&proc->todo, struct binder_work, entry);
        else {
            if (ptr - buffer == 4 && !(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN)) /* no data added */
                goto retry;
            break;
        }

        if (end - ptr < sizeof(tr) + 4)
            break;
        // 获取任务类型
        switch (w->type) {
        case BINDER_WORK_TRANSACTION: { // 唤醒后收到 BINDER_WORK_TRANSACTION
            t = container_of(w, struct binder_transaction, work);
        } break;
        case BINDER_WORK_TRANSACTION_COMPLETE: { // 唤醒需要时间,因此先收到 BINDER_WORK_TRANSACTION_COMPLETE
            cmd = BR_TRANSACTION_COMPLETE;
            // 将 cmd = BR_TRANSACTION_COMPLETE 写回到用户空间
            if (put_user(cmd, (uint32_t __user *)ptr))
                return -EFAULT;
            ptr += sizeof(uint32_t);
            
            binder_stat_br(proc, thread, cmd);
            
            list_del(&w->entry);
            kfree(w);
            binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
        } break;
        }
        
        // 收到 BINDER_WORK_TRANSACTION 时,t 不为空
        if (!t)
            continue;
        
        // 回复阶段 target_node 为空(请求阶段有值,回复阶段没有值)
        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;
            t->saved_priority = task_nice(current);
            if (t->priority < target_node->min_priority && !(t->flags & TF_ONE_WAY))
                binder_set_nice(t->priority);
            else if (!(t->flags & TF_ONE_WAY) || t->saved_priority > target_node->min_priority)
                binder_set_nice(target_node->min_priority);
            cmd = BR_TRANSACTION;
        } else { // 当前是 reply 回复阶段,走这个
            tr.target.ptr = NULL;
            tr.cookie = NULL;
            cmd = BR_REPLY; // BR_REPLY
        }
        tr.code = t->code;
        tr.flags = t->flags;
        tr.sender_euid = t->sender_euid;

        if (t->from) {
            struct task_struct *sender = t->from->proc->tsk;
            tr.sender_pid = task_tgid_nr_ns(sender, current->nsproxy->pid_ns);
        } else {
            tr.sender_pid = 0;
        }

        tr.data_size = t->buffer->data_size;
        tr.offsets_size = t->buffer->offsets_size;
        // tr(binder_transaction_data)数据缓冲区中有一个 type 为 BINDER_TYPE_HANDLE 的 Binder 引用对象,其中 handle 值由 Binder 驱动程序生成(handler -> binder_ref -> binder_node -> binder_proc)
        tr.data.ptr.buffer = (void *)t->buffer->data + proc->user_buffer_offset;
        tr.data.ptr.offsets = tr.data.ptr.buffer + ALIGN(t->buffer->data_size, sizeof(void *));

        // 将 cmd = BR_REPLY 写回到用户空间
        if (put_user(cmd, (uint32_t __user *)ptr))
            return -EFAULT;
        ptr += sizeof(uint32_t);
        // 将 tr(binder_transaction_data,数据缓冲区中有一个 type 为 BINDER_TYPE_HANDLE 的 Binder 引用对象,其中 handle 值由 Binder 驱动程序生成)写回到用户空间
        if (copy_to_user(ptr, &tr, sizeof(tr)))
            return -EFAULT;
        ptr += sizeof(tr);

        binder_stat_br(proc, thread, cmd);

        list_del(&t->work.entry);
        t->buffer->allow_user_free = 1;
        if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY)) {
            t->to_parent = thread->transaction_stack;
            t->to_thread = thread;
            thread->transaction_stack = t;
        } else {
            t->buffer->transaction = NULL;
            kfree(t);
            binder_stats_deleted(BINDER_STAT_TRANSACTION);
        }
        break;
    }

done:
    *consumed = ptr - buffer;
    if (proc->requested_threads + proc->ready_threads == 0 && // 正在请求的次数 + 空闲线程数 = 0,即两个都为 0
        proc->requested_threads_started < proc->max_threads && // 已创建的线程数 < 最大线程数(该值在 ProcessState.cpp 的 open_driver 中设置为 15)
        (thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED))) { // 当前线程是一个 Binder 线程(已注册成为 Binder 线程)
        proc->requested_threads++; // requested_threads + 1,则 if 条件不满足,一次只能增加一个线程,当线程增加成功后,驱动程序会将 requested_threads 会减一
        // 将返回协议 BR_SPAWN_LOOPER 写入到用户空间缓冲区 buffer,请求进程 proc 创建一个新的线程加入到 Binder 线程池中
        if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer))
            return -EFAULT;
    }
    // 返回
    return 0;
}

四、BR_REPLY

[–>binder.c, binder_parse()]
获取服务的进程在用户空间拿到内核空间保存的 binder_transaction_data(数据缓冲区中有一个 type 为 BINDER_TYPE_HANDLE 的 Binder 引用对象)

// bio = reply
// func = svcmgr_handler
int binder_parse(struct binder_state *bs, struct binder_io *bio,
                 uintptr_t ptr, size_t size, binder_handler func)
{
    int r = 1;
    uintptr_t end = ptr + (uintptr_t) size;

    while (ptr < end) {
        // 获取 cmd = BR_REPLY
        uint32_t cmd = *(uint32_t *) ptr;
        ptr += sizeof(uint32_t);
        switch(cmd) {
        case BR_REPLY: {
            // 获取返回协议 BR_REPLY 对应的数据 ptr,转为 binder_transaction_data
            struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
            if (bio) {
                // 解析从 Binder 驱动程序中读取到的进程间通信数据,去初始化 bio(这里 bio 就是 reply,当前方法是在给 reply 赋值)
                    // 解析数据,将 txn(binder_transaction_data)转为 bio(binder_io)
                bio_init_from_txn(bio, txn);
                bio = 0;
            }
            ptr += sizeof(*txn);
            r = 0;
            break;
        }
        default:
            return -1;
        }
    }

    return r;
}

方法返回后,reply 就有值了,可以从 reply 中获取到服务句柄值

五、Client 收到服务句柄 handle

从 reply 中获取服务句柄值

// 从 reply 中获取服务的 handle
uint32_t handle = bio_get_ref(&reply);

uint32_t bio_get_ref(struct binder_io *bio)
{
    struct flat_binder_object *obj;
    
    obj = _bio_get_obj(bio);
    if (!obj)
        return 0;

    if (obj->type == BINDER_TYPE_HANDLE)
        return obj->handle; // 返回 Binder 引用对象的 handle 值

    return 0;
}

六、获取服务句柄时序图

Binder—获取服务

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值