Binder—ServiceManager 启动过程

一、main:入口函数

[–>service_manager.c, main()]

int main(int argc, char **argv) {
    // 打开设备文件 driver = "/dev/binder",并映射设备文件到本进程地址空间
    bs = binder_open(driver, 128*1024);
    // 注册成为 Binder 进程间通信机制的上下文管理者
    binder_become_context_manager(bs);
    // 循环等待和处理 Client 进程的通信请求
    binder_loop(bs, svcmgr_handler);
}

// binder.c
struct binder_state
{
int fd; // 打开设备文件 “/dev/binder” 后得到的文件描述符(用于和 Binder 驱动程序交互)
void *mapped; // 映射设备文件后得到的地址空间的起始地址
size_t mapsize; // 映射设备文件后得到的地址空间的地址空间大小(默认为 128KB)
};

1.1 binder_open:打开和映射 Binder 设备文件

[–>binder.c, binder_open()]

// driver = "/dev/binder"
// mapsize = 128*1024
struct binder_state *binder_open(const char* driver, size_t mapsize) {
    struct binder_state *bs;
    
    // open():通过系统调用陷入内核,打开 Binder 设备驱动(会调用驱动的 binder_open 函数)
        // O_RDWR:读写模式
        // O_CLOEXEC:当调用 exec 成功后,文件描述符会自动关闭,在 open 中是原子操作
    bs->fd = open(driver, O_RDWR | O_CLOEXEC);
    if (bs->fd < 0) {
        goto fail_open; // 无法打开 Binder 设备
    }
	
    // 映射设备文件后得到的地址空间的地址空间大小,传入的是 128*1024(128KB)
    bs->mapsize = mapsize;
    // 映射设备文件后得到的地址空间的起始地址,mmap():通过系统调用,进行内存映射(必须是 page 的整数倍)
    bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
    if (bs->mapped == MAP_FAILED) {
        goto fail_map; // Binder 设备内存无法映射
    }
	
    return bs;

fail_map:
    close(bs->fd);
fail_open:
    free(bs);
    return NULL;
}

open 经过系统调用,进入 Binder 驱动,调用 binder_open(),该方法会在 Binder 驱动层创建一个 binder_proc 对象(用于描述当前进程的 Binder 进程间通信状态),再将 binder_proc 对象赋值给 fd->private_data,同时放入全局链表 binder_procs

mmap 经过系统调用,进入 Binder 驱动,调用 binder_mmap(),该方法会在 Binder 驱动层创建一个 binder_buffer 对象,并放入当前 binder_proc 的 proc->buffers 内核缓冲区链表

1.2 binder_become_context_manager:注册为 Binder 进程间通信机制的上下文管理者

[–>binder.c, binder_become_context_manager()]

static struct binder_node *binder_context_mgr_node;
static uid_t binder_context_mgr_uid = -1;

static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) {
    int ret;
    // 取出 binder_open 中给 ServiceManager 创建的 binder_proc
    struct binder_proc *proc = filp->private_data;
    struct binder_thread *thread;
    
    // 获取当前线程,首次创建并保存,之后直接返回
    thread = binder_get_thread(proc);
    
    // cmd = BINDER_SET_CONTEXT_MGR
    switch (cmd) {
    case BINDER_SET_CONTEXT_MGR:
        // binder_context_mgr_node 默认为空,不为空说明当前已注册为 Binder 进程间通信机制的上下文管理者
        if (binder_context_mgr_node != NULL) {
            ret = -EBUSY;
            goto err;
        }
        // binder_context_mgr_uid 默认为 -1,不为 -1 说明其它进程已注册 Binder 进程间通信机制的上下文管理者
        if (binder_context_mgr_uid != -1) {
            // binder_context_mgr_uid 不是当前进程的有效用户 id
            if (binder_context_mgr_uid != current->cred->euid) {
                ret = -EPERM;
                goto err; // 出错
            }
        } else // binder_context_mgr_uid 默认为 -1
            // binder_context_mgr_uid 赋值为当前进程的有效用户 id
            binder_context_mgr_uid = current->cred->euid;
        // 为 ServiceManager 创建一个 Binder 实体对象
        binder_context_mgr_node = binder_new_node(proc, NULL, NULL);
        if (binder_context_mgr_node == NULL) {
            ret = -ENOMEM;
            goto err;
        }
        binder_context_mgr_node->local_weak_refs++;
        binder_context_mgr_node->local_strong_refs++;
        binder_context_mgr_node->has_strong_ref = 1;
        binder_context_mgr_node->has_weak_ref = 1;
        break;
    }
}

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

// ptr = NULL
// cookie = NULL
static struct binder_node *binder_new_node(struct binder_proc *proc, 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;
    
    // 首次进入,红黑树中没有节点,跳过 while 循环
    while (*p) {
        parent = *p;
        node = rb_entry(parent, struct binder_node, rb_node);
        
        if (ptr < node->ptr)
            p = &(*p)->rb_left;
        else if (ptr > node->ptr)
            p = &(*p)->rb_right;
        else
            return NULL;
    }
	
    // 创建一个 Binder 实体对象,并且对它进行初始化,最后将它加入到宿主进程的成员变量 nodes 红黑树中
    node = kzalloc(sizeof(*node), GFP_KERNEL); // 分配内核空间
    if (node == NULL)
        return NULL;
    binder_stats_created(BINDER_STAT_NODE);
    // 将新创建的 node 对象添加到 proc 红黑树
    rb_link_node(&node->rb_node, parent, p);
    rb_insert_color(&node->rb_node, &proc->nodes);
    node->debug_id = ++binder_last_id;
    // 将传入的 proc:binder_proc* 加入到 node:binder_node* 的 proc
    node->proc = proc;
    node->ptr = ptr;
    node->cookie = cookie;
    // 设置 binder_work 的 type
    node->work.type = BINDER_WORK_NODE;
    INIT_LIST_HEAD(&node->work.entry);
    INIT_LIST_HEAD(&node->async_todo);
    return node;
}

&(*p)->rb_left
&(*p)->rb_left = &((*p)->rb_left)
-> 的优先级比 & 高

首次进入 binder_new_node:

  • 会在 Binder 驱动层创建 binder_node 实体对象
  • 将当前 binder_proc 加入到 binder_node 的 proc
  • 创建 binder_node 的 async_todo 和 binder_work.entry 两个队列

1.3 binder_loop:循环等待 Client 进程请求

[–>binder.c, binder_loop()]

void binder_loop(struct binder_state *bs, binder_handler func) {
    int res;
    struct binder_write_read bwr;
    uint32_t readbuf[32];
    
    readbuf[0] = BC_ENTER_LOOPER;
    // 发送命令协议 BC_ENTER_LOOPER 给 Binder 驱动,将 Service Manager 进程主线程注册为 Binder 线程
    binder_write(bs, readbuf, sizeof(uint32_t));
    	
    bwr.write_size = 0; // 进程用户态地址空间传递到内核数据的大小
    bwr.write_consumed = 0; // 进程用户态地址空间传递到内核数据中已经被内核态处理的大小
    bwr.write_buffer = 0; // 进程用户态地址空间传递到内核数据的起始地址
    
    for (;;) { // 进入循环,不断地 binder 读写过程
        // 每次循环前,重置 read 相关的参数
        bwr.read_size = sizeof(readbuf); // 总共可供给驱动写入的字节数,read_buffer 可供内核使用的大小
        bwr.read_consumed = 0;
        bwr.read_buffer = (uintptr_t)readbuf; // 内核驱动发送给进程数据 buffer 的起始地址
        
        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
        if (res < 0) {
            break;
        }
		
        // 解析 binder 信息
        res = binder_parse(bs, 0, (uintptr_t)readbuf, bwr.read_consumed, func); // func 传入的是 svcmgr_handler
        if (res == 0) {
            break;
        }
        if (res < 0) {
            break;
        }
    }
}

[–>binder.c, binder_write()]

// data = BC_ENTER_LOOPER
int binder_write(struct binder_state *bs, void *data, size_t len)
{
    struct binder_write_read bwr;
    int res;
    
    bwr.write_size = len; // len 传入的是 sizeof(uint32_t),大小为 4
    bwr.write_consumed = 0;
    // write_buffer 指向缓冲区的起始地址,其内容为 BC_ENTER_LOOPER 请求协议号
    bwr.write_buffer = (uintptr_t) data;
    bwr.read_size = 0;
    bwr.read_consumed = 0;
    bwr.read_buffer = 0;
    
    // 调用驱动 binder_ioctl
        // write_size 大于 0,read_size 等于 0,只写不读,写完立马返回用户空间
    res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
    return res;
}

通过 ioctl() 将 binder_write_read 数据发给 Binder 驱动,调用 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 中给 ServiceManager 创建的 binder_proc
    struct binder_roc *proc = filp->private_ata;
    struct binder_thread *thread;
    void __user *ubuf = (void __user *)arg;
    
    // 获取当前线程对应的 binder_thread,在 binder_become_context_manager 中已创建,这里直接返回
    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 只包含 BC_ENTER_LOOPER
        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_ENTER_LOOPER
        if (get_user(cmd, (uint32_t __user *)ptr))
            return -EFAULT;
        ptr += sizeof(uint32_t);
        
        // cmd = BC_ENTER_LOOPER
        switch (cmd) {
            case BC_ENTER_LOOPER:
                // 设置线程的 looper 状态为 BINDER_LOOPER_STATE_ENTERED
                thread->looper |= BINDER_LOOPER_STATE_ENTERED;
                break;
        }
        *consumed = ptr - buffer;
    }
    return 0;
}

binder_thread_write 处理完命令协议 BC_ENTER_LOOPER 后,返回 binder_ioctl 中,然后返回到用户空间的 binder_write 中,最后返回到 binder_loop,开始执行 for 循环中的内容

[–>binder.c, binder_loop()]

void binder_loop(struct binder_state *bs, binder_handler func) {
    
    ...
    
    for (;;) { // 进入循环,不断地 binder 读写过程
        // 每次循环前,重置 read 相关的参数
        bwr.read_size = sizeof(readbuf); // 总共可供给驱动写入的字节数,read_buffer 可供内核使用的大小
        bwr.read_consumed = 0;
        bwr.read_buffer = (uintptr_t)readbuf; // 内核驱动发送给进程数据 buffer 的起始地址
        
        // 调用驱动 binder_ioctl
            // read_size 大于 0,write_size 等于 0,只读不写
        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
        if (res < 0) {
            break;
        }
		
        // 解析 binder 信息
        res = binder_parse(bs, 0, (uintptr_t)readbuf, bwr.read_consumed, func); // func 传入的是 svcmgr_handler
        if (res == 0) {
            break;
        }
        if (res < 0) {
            break;
        }
    }
}

[–>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 中给 ServiceManager 创建的 binder_proc
    struct binder_roc *proc = filp->private_ata;
    struct binder_thread *thread;
    void __user *ubuf = (void __user *)arg;
    
    // 获取当前线程对应的 binder_thread,在 binder_become_context_manager 中已创建,这里直接返回
    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;
        }

        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;
            }
        }
        // 拷贝的 bwr 中,只有 read_size 大于 0,read_buffer 用于接收内核驱动发送给进程 ServiceManager 的数据
        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_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 *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) {
        ... // 暂不分析处理工作项(假定暂无需要处理的工作项)
    }

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;
}

至此, ServiceManager 进程启动过程分析完毕。若 ServiceManager 进程的主线程没有待处理的工作项,则此时就会睡眠在 Binder 驱动程序的 binder_thread_read 中,等待 Client 进程(向 Server 进程 ServiceManager 发送请求)的 Service 组件(向 Client 进程提供服务)或 Client 组件(Service 代理对象,向 Server 进程请求服务)

这里的 Service 组件和 Client 组件是 Binder 进程间通信机制中的概念

二、ServiceManager 启动过程时序图

启动 ServiceManager

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值