Binder学习[1]: ServiceManger 如何成为所有Service的管理进程

本文主要解析两个关键点:

  1. ServiceManger 如何成为所有Service的管理进程
  2. ServiceManager 与 Binder Driver 共享 128K 内存

我们从ServiceManager的 main函数开始(service_manager.c):

int main()
{
    struct binder_state *bs;

    bs = binder_open(128*1024);
    ...
    binder_become_context_manager(bs);
    ...
    binder_loop(bs, svcmgr_handler);
    return  0;
}

从其main函数可以看到,ServiceManager进程主要通过这三个函数的执行,使得其成为 Service的管理进程,我们依次来说;

1.binder_open

我们看下binder_open函数(代码在 /frameworks/native/cmds/servicemanager/binder.c), 这里摘取了函数的主要逻辑:

struct binder_state *binder_open(size_t mapsize)
{
    struct binder_state *bs;
    struct binder_version vers;

    bs = malloc(sizeof(*bs));
    ...
    bs->fd = open("/dev/binder", O_RDWR | O_CLOEXEC);
    ...
    if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
        (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
        goto fail_open;
    }
    ...
    bs->mapsize = mapsize;
    bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
    ...
    return bs;
}

其中 bs 是一个struct:

struct binder_state
{
    int fd;
    void *mapped;
    size_t mapsize;
};

bs->fd : 保存着打开的 binder driver节点 "/dev/binder"对应的文件描述符, 待 ServiceManager 进程与 binder driver通信时,

会使用到这个fd;

bs->mmaped : 保存着 mmap 返回的用户态虚拟地址;

bs->mapsize :128 KB

 

函数首先调用 malloc 给 bs分配一块内存,这个没什么可说的;

接下来 open 函数会打开 binder driver对应的字符设备节点 "/dev/binder",对于用户态来说,目的就是返回了一个 fd;

而由于 binder driver 注册,而对于这个节点的 open操作,最终经过 open 系统调用后,会调用 binder driver的 binder_open函数,binder driver的 binder_open 函数 (kernel/drivers/android/binder.c):

static int binder_open(struct inode *nodp, struct file *filp)
{
	struct binder_proc *proc; //每个要进行binder通信的进程都有一个对应的 binder_proc
        ...
	proc = kzalloc(sizeof(*proc), GFP_KERNEL); //在kernel为调用open的进程分配binder_proc 
        ...
	get_task_struct(current);
	proc->tsk = current;  //设置该 binder_proc的 task指向调用 open的进程
	INIT_LIST_HEAD(&proc->todo); //初始化todo list,这个list用来保存将要进行的通信工作
	init_waitqueue_head(&proc->wait);//初始化 wait,即正在睡眠的 binder 线程list
	proc->default_priority = task_nice(current);//进程优先级
	hlist_add_head(&proc->proc_node, &binder_procs);//把 proc添加到binder_procs list中
	proc->pid = current->group_leader->pid; //记录当前进程 pid
	INIT_LIST_HEAD(&proc->delivered_death); //death list
	filp->private_data = proc;  //把 proc记录到 file的 private_data

        return 0;
}

这里面的操作主要是 创建一个 binder_proc,初始化一些数据,并把 binder_proc保存到service_manager进程打开 "/dev/binder"时,

创建的 filp->private_data中。binder_proc是每个要进行 binder通信都需要的一个数据结构,与进程关系是一对一 ,其保存进程binder通信时使用到的一些数据。

下面我们看一下 binder_proc:

struct binder_proc {
    // 进程打开设备文件/dev/binder时,Binder驱动会为它创建一个binder_proc结构体,并将它
    // 保存在全局hash列表中,proc_node是该hash列表的节点。
    struct hlist_node proc_node;

    // 每个使用了Binder机制的进程都有一个Binder线程池,用来处理进程间通信请求。threads以
    // 线程ID作为key来组织进程的Binder线程池。进程可以调用ioctl将线程注册到Binder驱动中
    // 当没有足够的空闲线程处理进程间通信请求时,驱动可以要求进程注册更多的线程到Binder线程
    // 池中
    struct rb_root threads; 

    struct rb_root nodes;           // 组织Binder实体对象,它以成员ptr作为key
    struct rb_root refs_by_desc;    // 组织Binder引用对象,它以成员desc作为key
    struct rb_root refs_by_node;    // 组织Binder引用对象,它以成员node作为key
    int pid;                        // 指向进程组ID
    struct vm_area_struct *vma;     // 内核缓冲区的用户空间地址,供应用程序使用
    struct mm_struct *vma_vm_mm;
    struct task_struct *tsk;        // 指向进程任务控制块
    struct files_struct *files;     // 指向进程打开文件结构体数组

    // 一个hash表,保存进程可以延迟执行的工作项,这些延迟工作有三种类型
    // BINDER_DEFERRED_PUT_FILES、BINDER_DEFERRED_FLUSH、BINDER_DEFERRED_RELEASE
    // 驱动为进程分配内核缓冲区时,会为该缓冲区创建一个文件描述符,进程可以通过该描述符将该内
    // 核缓冲区映射到自己的地址空间。当进程不再需要使用Binder机制时,就会通知驱动关闭该文件
    // 描述符并释放之前所分配的内核缓冲区。由于这不是一个马上就要完成的操作,因此驱动会创建一
    // 个BINDER_DEFERRED_PUT_FILES类型的工作来延迟执行;
    // Binder线程池中的空闲Binder线程是睡眠在一个等待队列中的,进程可以通过调用函数flush
    // 来唤醒这些线程,以便它们可以检查进程是否有新的工作项需要处理。此时驱动会创建一个
    // BINDER_DEFERRED_FLUSH类型的工作项,以便延迟执行唤醒空闲Binder线程的操作;
    // 当进程不再使用Binder机制时,会调用函数close关闭文件/dev/binder,此时驱动会释放之
    // 前为它分配的资源,由于资源释放是个比较耗时的操作,驱动会创建一个
    // BINDER_DEFERRED_RELEASE类型的事务来延迟执行
    struct hlist_node deferred_work_node;

    int deferred_work;              // 描述该延迟工作项的具体类型
    void *buffer;                   // 内核缓冲区的内核空间地址,供驱动程序使用
    ptrdiff_t user_buffer_offset;   // vma和buffer之间的差值

    // buffer指向一块大的内核缓冲区,驱动程序为方便管理,将它划分成若干小块,这些小块的内核缓
    // 冲区用binder_buffer描述保存在列表中,按地址从小到大排列。buffers指向该列表的头部。
    struct list_head buffers; 

    struct rb_root free_buffers;      // buffers中的小块有的正在使用,被保存在此红黑树
    struct rb_root allocated_buffers;   // buffers中的空闲小块被保存在此红黑树
    size_t free_async_space;            // 当前可用的保存异步事务数据的内核缓冲区的大小

    struct page **pages;    // buffer和vma都是虚拟地址,它们对应的物理页面保存在pages
                            // 中,这是一个数组,每个元素指向一个物理页面
    size_t buffer_size;     // 进程调用mmap将它映射到进程地址空间,实际上是请求驱动为它
                            // 分配一块内核缓冲区,缓冲区大小保存在该成员中
    uint32_t buffer_free;   // 空闲内核缓冲区的大小
    struct list_head todo;  // 当进程接收到一个进程间通信请求时,Binder驱动就将该请求封
                            // 装成一个工作项,并且加入到进程的待处理工作向队列中,该队列
                            // 使用成员变量todo来描述。
    wait_queue_head_t wait; // 线程池中空闲Binder线程会睡眠在由该成员所描述的等待队列中
                            // 当宿主进程的待处理工作项队列增加新工作项后,驱动会唤醒这
                            // 些线程,以便处理新的工作项
    struct binder_stats stats;  // 用来统计进程数据

    // 当进程所引用的Service组件死亡时,驱动会向该进程发送一个死亡通知。这个正在发出的通知被
    // 封装成一个类型为BINDER_WORK_DEAD_BINDER或BINDER_WORK_DEAD_BINDER_AND_CLEAR
    // 的工作项,并保存在由该成员描述的队列中删除
    struct list_head delivered_death;  

    int max_threads;        // 驱动程序最多可以主动请求进程注册的线程数
    int requested_threads;
    int requested_threads_started;
    int ready_threads;      // 进程当前的空闲Binder线程数
    long default_priority;  // 进程的优先级,当线程处理一个工作项时,线程优先级可能被
                            // 设置为宿主进程的优先级
    struct dentry *debugfs_entry;
};

总结:用户进程调用open("/dev/binder"),其实做了2个工作:

  1. 记录一个文件描述符 fd到用户进程,以便后面与 binder driver 通信
  2. 内核中执行内核的 binder_open 函数,为该用户进程创建一个对应的 binder_proc,以便通信使用

接下来,ServiceManager中的 binder_open函数会依次执行 version校验 和 mmap操作,分到下面两节来说。

2.version校验

对应代码是:

    if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
        (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
        goto fail_open;
    }

就是从获取一下binder driver中的binder的版本,比较是否与 service manger使用 binder 版本匹配;

主要工作在 binder version的获取,是通过 ioctl来获取的。

ioctl(bs->fd, BINDER_VERSION, &vers);

刚才记录的 bs->fd就是用来做 ioctl通信的,发的命令是 BINDER_VERSION,得到的version记录在 vers中。

ioctl经过系统调用后,会调用到 binder driver的 binder_ioctl 函数,这里只摘录跟本次调用 相关的代码:

static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	int ret;
	struct binder_proc *proc = filp->private_data;//这个filp就是servicemanager进程打开 "/dev/binder"节点是对应的进程,之前把 proc记录到了其 private_data中
	struct binder_thread *thread;
	unsigned int size = _IOC_SIZE(cmd); // cmd, BINDER_VERSION
	void __user *ubuf = (void __user *)arg;//对应上面的 vers
        ...
	thread = binder_get_thread(proc);//从proc->threads.rb_node中找,找不到则创建一个,并记录
	switch (cmd) {
        ...
	case BINDER_VERSION: {
		struct binder_version __user *ver = ubuf;

		if (size != sizeof(struct binder_version)) {
			ret = -EINVAL;
			goto err;
		}
		if (put_user_preempt_disabled(BINDER_CURRENT_PROTOCOL_VERSION,
			     &ver->protocol_version)) {//把 binder driver version写入到 vers中,这样返回后,Servicemanger中 binder_open函数的局部变量 vers中就有数据了
			ret = -EINVAL;
			goto err;
		}
		break;
	}
	}
	ret = 0;
	if (thread)
		thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN;
	return ret; //正常返回
}

完成binder dirver的vers获取,即可进行对比验证。

接下来是:     bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);

 

3.binder_mmap

 

service manager 的 version校验办成后,接下来就是mmap,

bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);

这个函数主要完成两件事情:

  1. 把 mmap 128KB 返回的service manager进程的用户空间地址记录到  bs->mmaped
  2. 在内核调用 binder driver的 binder_mmap函数,为进程在内核空间申请 128K虚拟内存,在用户空间也申请 128K虚拟内存;并先 alloc一个 PAGE的物理内存以便使用,后续需要的的时候,再真正分配物理页面

实际上,kernel空间的 128K 虚拟内存,和用户空间的 128K虚拟内存,在使用时,是会对应到相同的物理内存的。代码如下:

static int binder_mmap(struct file *filp, struct vm_area_struct *vma)
{
	int ret;

	struct vm_struct *area;
	struct binder_proc *proc = filp->private_data;
	const char *failure_string;
	struct binder_buffer *buffer;
        ...
	if ((vma->vm_end - vma->vm_start) > SZ_4M)
		vma->vm_end = vma->vm_start + SZ_4M;//每个进程的binder通信内存最大不能超过4M
        ...
	area = get_vm_area(vma->vm_end - vma->vm_start, VM_IOREMAP); //分配内核虚拟内存属性
	proc->buffer = area->addr; //指向内核虚拟内存起始位置
	proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer;//记录 offset
	proc->pages = kzalloc(sizeof(proc->pages[0]) * ((vma->vm_end - vma->vm_start) / PAGE_SIZE), GFP_KERNEL);//分配虚拟内存用以记录物理页面对应的指针
	proc->buffer_size = vma->vm_end - vma->vm_start;//buffer size

	vma->vm_ops = &binder_vm_ops;
	vma->vm_private_data = proc;
	ret = binder_update_page_range(proc, 1, proc->buffer, proc->buffer + PAGE_SIZE, vma); //分配一个 PAGE 的实际物理页面,并通过vma与用户空间虚拟地址绑定,通过 proc->pages与内核空间虚拟地址绑定起来
	buffer = proc->buffer;
	INIT_LIST_HEAD(&proc->buffers);
	list_add(&buffer->entry, &proc->buffers);
	buffer->free = 1;
	binder_insert_free_buffer(proc, buffer);
	proc->free_async_space = proc->buffer_size / 2;
	barrier();
	proc->files = get_files_struct(current);
	proc->vma = vma;
	proc->vma_vm_mm = vma->vm_mm;
	return 0;
}

binder_mmap完成后,kernel 128K虚拟内存和 service manger 进程的 128K虚拟内存关系如下:

其实解释了ServiceManger 与 binder driver如何共享的 128K内存;

 

这样就解释了binder一次内存拷贝的原理:

当一个进程 B 想和 ServiceManger通信时,自己组织好的数据data(用户态的内存地址),调用 binder_ioctl 进入内核态,binder driver找到 service manager记录在内核中的 binder node,取出其 binder_proc, 把 data 内容拷贝到 binder_proc中记录的内核中servicemanger进程对应的128K内存首地址:binder_proc->buffer,当拷贝完成(data已经写入物理内存),由于 service manger进程用户态 128K 虚拟内存对应的也是这段物理内存,所以,此时从 servicemanager进程读取它 128K虚拟内存的数据,访问的物理内存与 kernel中是同一个,已经有data数据了,这就是binder一次拷贝的秘密 。

 

 

4.binder_become_context_manager(bs)

 

在 service_manager.c main函数执行完 binder_open函数后,接下来执行 binder_become_context_manager(bs)函数:

int binder_become_context_manager(struct binder_state *bs)
{
    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}

static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	int ret;
	struct binder_proc *proc = filp->private_data;//这个filp就是servicemanager进程打开 "/dev/binder"节点是对应的进程,之前把 proc记录到了其 private_data中
	struct binder_thread *thread;
	unsigned int size = _IOC_SIZE(cmd); // cmd, BINDER_VERSION
	void __user *ubuf = (void __user *)arg;//这次的arg是0,用不到
        ...
	thread = binder_get_thread(proc);//从proc->threads.rb_node中找,找不到则创建一个,并记录
	switch (cmd) {
        ...
	case BINDER_SET_CONTEXT_MGR:
		ret = binder_ioctl_set_ctx_mgr(filp);
		if (ret)
			goto err;
		break;
           ...
	}
	ret = 0;
	if (thread)
		thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN;
	return ret;
}

接下来调用 binder_ioctl_set_ctx_mgr(filp):

static int binder_ioctl_set_ctx_mgr(struct file *filp)
{
	int ret = 0;
	struct binder_proc *proc = filp->private_data;
	kuid_t curr_euid = current_euid();

	if (binder_context_mgr_node != NULL) { //如果已经有context mgr,则创建失败
		ret = -EBUSY;
		goto out;
	}
	if (uid_valid(binder_context_mgr_uid)) { //检查权限
		if (!uid_eq(binder_context_mgr_uid, curr_euid)) {
			ret = -EPERM;
			goto out;
		}
	} else {
		binder_context_mgr_uid = curr_euid;
	}
	binder_context_mgr_node = binder_new_node(proc, 0, 0);//创建一个新的 binder node,其中两个0代表binder node的 ptr和 cookie都是 0,proc代表这个node对应的进程
	if (binder_context_mgr_node == NULL) {
		ret = -ENOMEM;
		goto out;
	}
	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;
out:
	return ret;
}

看下 binder_new_node:

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

	node = kzalloc_preempt_disabled(sizeof(*node));
	if (node == NULL)
		return NULL;
	binder_stats_created(BINDER_STAT_NODE);
	rb_link_node(&node->rb_node, parent, p);
	rb_insert_color(&node->rb_node, &proc->nodes);
	node->debug_id = ++binder_last_id;
	node->proc = proc;//当前node的proc就是 servce mangager进程对应的binder 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);
	binder_debug(BINDER_DEBUG_INTERNAL_REFS,
		     "%d:%d node %d u%016llx c%016llx created\n",
		     proc->pid, current->pid, node->debug_id,
		     (u64)node->ptr, (u64)node->cookie);
	return node;
}
总结:所以 binder_become_context_manager(bs)这个函数调用使得 内核中 binder driver 创建了一个新的binder node,记录到 binder_context_mgr_node,这个node是唯一的,其记录这个 node对应的进程是 service manger进程。所以 service manger成为所有需要binder通信的Service的管理进程就是这么来的。

 

 

5.binder_loop

在 service_manager.c main函数执行完binder_become_context_manager(bs)函数后,就要执行函数:   

binder_loop(bs, svcmgr_handler);

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;
    binder_write(bs, readbuf, sizeof(uint32_t));//通知binder driver进入LOOP

    for (;;) {
        bwr.read_size = sizeof(readbuf);
        bwr.read_consumed = 0;
        bwr.read_buffer = (uintptr_t) readbuf;

        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);//开始从128K 内存中读取数据,可能block在这

        if (res < 0) {
            ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
            break;
        }

        res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);//读取到数据后处理数据
        if (res == 0) {
            ALOGE("binder_loop: unexpected reply?!\n");
            break;
        }
        if (res < 0) {
            ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
            break;
        }
    }
}
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;
    res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
    if (res < 0) {
        fprintf(stderr,"binder_write: ioctl failed (%s)\n",
                strerror(errno));
    }
    return res;
}

这里构建了一个binder_write_read 数据 bwr来进行和 driver通话,这里有必要解释以下 bwr:

struct binder_write_read {
 signed long write_size; //要写入的数据大小
 signed long write_consumed; //写入数据对于buffer的偏移
 unsigned long write_buffer; //要写入的数据从write_buffer中获取
 signed long read_size; //读取。。
 signed long read_consumed;
 unsigned long read_buffer; //读取的数据保存到 read_buffer
};

所以 binder_loop函数先通过 binder_write(fd, buffer, 4)组织数据到 bwr,这里 buffer中只存放了一个数据: "BC_ENTER_LOOPER",然后调用 ioctl(fd, BINDER_WRITE_READ, &bwr)与 binder driver通信。

这个 bwr和 buffer都在用户空间。我们先图示化一下要 bwr参数,方便后面解析这个参数:

这里又到了 binder_ioctl,只不过这次的cmd是 BINDER_WRITE_READ:

static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	int ret;
	struct binder_proc *proc = filp->private_data;//这个filp就是servicemanager进程打开 "/dev/binder"节点是对应的进程,之前把 proc记录到了其 private_data中
	struct binder_thread *thread;
	unsigned int size = _IOC_SIZE(cmd); // cmd, BINDER_VERSION
	void __user *ubuf = (void __user *)arg;//这次arg对应bwr
        ...
	thread = binder_get_thread(proc);//从proc->threads.rb_node中找,找不到则创建一个,并记录
	switch (cmd) {
	case BINDER_WRITE_READ:
		ret = binder_ioctl_write_read(filp, cmd, arg, thread);//arg原封不动传递过去
		if (ret)
			goto err;
		break;
        ...
	}
	ret = 0;
	if (thread)
		thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN;
	return ret;
}

命令 BINDER_WRITE_READ会使得 binder driver调用 binder_ioctl_write_read(filp, cmd, arg, thread);

我么可以看到 arg(也就是上面的 bwr)被原封不动的传递过去了。我们看看binder_ioctl_write_read有没有解析 arg参数:

2625static int binder_ioctl_write_read(struct file *filp,
2626				unsigned int cmd, unsigned long arg,
2627				struct binder_thread *thread)
2628{
2629	int ret = 0;
2630	struct binder_proc *proc = filp->private_data;
2631	unsigned int size = _IOC_SIZE(cmd);//每个cmd对应参数size不同,而只有BINDER_WRITE_READ cmd会走到这个函数,其对应的size是固定的
2632	void __user *ubuf = (void __user *)arg;//arg指向 bwr(用户态地址)
2633	struct binder_write_read bwr;//这里在内核分配一个bwr用来存放传过来的参数
2634
2635	if (size != sizeof(struct binder_write_read)) {
2636		ret = -EINVAL;
2637		goto out;
2638	}
2639	if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {//把传过来的bwr数据拷贝到内核中的 bwr中,注意,bwr中write_buffer仍指向用户态的那个 buffer
2640		ret = -EFAULT;
2641		goto out;
2642	}
2643	binder_debug(BINDER_DEBUG_READ_WRITE,
2644		     "%d:%d write %lld at %016llx, read %lld at %016llx\n",
2645		     proc->pid, thread->pid,
2646		     (u64)bwr.write_size, (u64)bwr.write_buffer,
2647		     (u64)bwr.read_size, (u64)bwr.read_buffer);
2648
2649	if (bwr.write_size > 0) {//如果 write_size>0,先write
2650		ret = binder_thread_write(proc, thread,
2651					  bwr.write_buffer,//指向用户空间buf
2652					  bwr.write_size,
2653					  &bwr.write_consumed);
2654		trace_binder_write_done(ret);
2655		if (ret < 0) {//write成功时,ret是0;小于0代表失败
2656			bwr.read_consumed = 0;
2657			if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
2658				ret = -EFAULT;
2659			goto out;
2660		}
2661	}
2662	if (bwr.read_size > 0) {//如果需要 read,再进行read
2663		ret = binder_thread_read(proc, thread, bwr.read_buffer,
2664					 bwr.read_size,
2665					 &bwr.read_consumed,
2666					 filp->f_flags & O_NONBLOCK);
2667		trace_binder_read_done(ret);
2668		if (!list_empty(&proc->todo))
2669			wake_up_interruptible(&proc->wait);
2670		if (ret < 0) {//read成功时,ret是0;小于0代表失败
2671			if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
2672				ret = -EFAULT;
2673			goto out;
2674		}
2675	}
2676	binder_debug(BINDER_DEBUG_READ_WRITE,
2677		     "%d:%d wrote %lld of %lld, read return %lld of %lld\n",
2678		     proc->pid, thread->pid,
2679		     (u64)bwr.write_consumed, (u64)bwr.write_size,
2680		     (u64)bwr.read_consumed, (u64)bwr.read_size);
2681	if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {//把read/write结束的数据写回user space的 buffer中
2682		ret = -EFAULT;
2683		goto out;
2684	}
2685out:
2686	return ret;
2687}


1754static int binder_thread_write(struct binder_proc *proc,
1755			struct binder_thread *thread,
1756			binder_uintptr_t binder_buffer, size_t size,
1757			binder_size_t *consumed)
1758{
1759	uint32_t cmd;
1760	void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
1761	void __user *ptr = buffer + *consumed;//ptr指向用户空间buffer位置
1762	void __user *end = buffer + size;
1763
1764	while (ptr < end && thread->return_error == BR_OK) {
1765		if (get_user(cmd, (uint32_t __user *)ptr))//从用户空间buf起始位置读取cmd,我们buf中保存的是:"BC_ENTER_LOOPER"
1766			return -EFAULT;
1767		ptr += sizeof(uint32_t);//ptr向前移动sizeof(cmd)
1768		trace_binder_command(cmd);
1769		if (_IOC_NR(cmd) < ARRAY_SIZE(binder_stats.bc)) {
1770			binder_stats.bc[_IOC_NR(cmd)]++;
1771			proc->stats.bc[_IOC_NR(cmd)]++;
1772			thread->stats.bc[_IOC_NR(cmd)]++;
1773		}
1774		switch (cmd) {
...             //函数较大,只摘取本次相关代码
1961		case BC_ENTER_LOOPER:
1962			binder_debug(BINDER_DEBUG_THREADS,
1963				     "%d:%d BC_ENTER_LOOPER\n",
1964				     proc->pid, thread->pid);
1965			if (thread->looper & BINDER_LOOPER_STATE_REGISTERED) {
1966				thread->looper |= BINDER_LOOPER_STATE_INVALID;
1967				binder_user_error("%d:%d ERROR: BC_ENTER_LOOPER called after BC_REGISTER_LOOPER\n",
1968					proc->pid, thread->pid);
1969			}
1970			thread->looper |= BINDER_LOOPER_STATE_ENTERED;//只是设置了一下当前 binder_thread 的状态
1971			break;
...
2107		default:
2108			pr_err("%d:%d unknown command %d\n",
2109			       proc->pid, thread->pid, cmd);
2110			return -EINVAL;
2111		}
2112		*consumed = ptr - buffer;//更新bwr.write_consumed = 4,注意这个bwr是内核中的 bwr
2113	}
2114	return 0;
2115}

所以此时内核中的 bwr数据:

注意,kernel bwr数据是从用户空间拷贝过来的,而这里只把write_consumed 从 0改了4,所以上面就是 kernel bwr现在的数据了。

修改完 write_consumed后,就从 binder_thread_write函数返回到 binder_ioctl_write_read函数,由于当前不需要read,所以会继续走到如下代码:

2681	if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {//把read/write结束的数据写回user space的 buffer中
2682		ret = -EFAULT;
2683		goto out;
2684	}

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;
    res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
    if (res < 0) {
        fprintf(stderr,"binder_write: ioctl failed (%s)\n",
                strerror(errno));
    }
    return res;
}

这里调用完成 ioctl返回后,并没有再使用 bwr了,我们不再关注bwr。但我们知道了 BINDER_WRITE_READ 执行完成后,会回写修改后的 bwr 数据到 user space,那么user space就可以再 ioctl(..., BINDER_WRITE_READ , &bwr)函数返回后,通过 bwr数据得到一些 driver执行的信息,比如就通过刚才那个 bwr.write_consumed 和 bwr.write_size比较,从而判断有没有把数据write完成。

到这里,binder_write函数就返回了,接下来又回到了 service manger的 binder_loop函数:

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;
    binder_write(bs, readbuf, sizeof(uint32_t));//通知binder driver进入LOOP

    for (;;) {
        bwr.read_size = sizeof(readbuf);
        bwr.read_consumed = 0;
        bwr.read_buffer = (uintptr_t) readbuf;

        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);//开始从128K 内存中读取数据,可能block在这

        if (res < 0) {
            ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
            break;
        }

        res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);//读取到数据后处理数据
        if (res == 0) {
            ALOGE("binder_loop: unexpected reply?!\n");
            break;
        }
        if (res < 0) {
            ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
            break;
        }
    }
}

可以看到 binder_write函数返回后,service manger 进程就会进入 for循环,进行反复的读取,解析binder请求的动作了。这里调用 ioctl指令是 BINDER_WRITE_READ ,为什么我么说读取,而没有写入呢?请注意这里的 bwr:

这里同样会走到 binder_ioctl_write_read函数,可以去前面看下,不同的是,这次只会走到 read分支:

2662	if (bwr.read_size > 0) {//如果需要 read,再进行read
2663		ret = binder_thread_read(proc, thread, bwr.read_buffer,
2664					 bwr.read_size,
2665					 &bwr.read_consumed,
2666					 filp->f_flags & O_NONBLOCK);//这参数代表是否 block
....
2675	}

问:filp->f_flags时在那里设置的呢?O_NONBLOCK又时什么意思?

可以看到,传递了 bwr.read_consumed,这样后续把 bwr拷贝回用户空间时,用户空间进程就能知道本次的binder read读到了多少数据;

2141static int binder_thread_read(struct binder_proc *proc,
2142			      struct binder_thread *thread,
2143			      binder_uintptr_t binder_buffer, size_t size,
2144			      binder_size_t *consumed, int non_block)
2145{
2146	void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
2147	void __user *ptr = buffer + *consumed;//buffer的开始使用的位置
2148	void __user *end = buffer + size;//buffer末尾
2149
2150	int ret = 0;
2151	int wait_for_proc_work;
2152
2153	if (*consumed == 0) {
2154		if (put_user(BR_NOOP, (uint32_t __user *)ptr))//写BR_LOOP占位
2155			return -EFAULT;
2156		ptr += sizeof(uint32_t);//更新 ptr
2157	}
2158
2159retry:
2160	wait_for_proc_work = thread->transaction_stack == NULL &&
2161				list_empty(&thread->todo);//如果binder thread 没有binder请求需要处理,wait_for_proc_work置为 true,代表需要等待从 binder_proc获取binder请求
2162
2163	if (thread->return_error != BR_OK && ptr < end) {//错误处理,暂时跳过
2164		if (thread->return_error2 != BR_OK) {
2165			if (put_user(thread->return_error2, (uint32_t __user *)ptr))
2166				return -EFAULT;
2167			ptr += sizeof(uint32_t);
2168			binder_stat_br(proc, thread, thread->return_error2);
2169			if (ptr == end)
2170				goto done;
2171			thread->return_error2 = BR_OK;
2172		}
2173		if (put_user(thread->return_error, (uint32_t __user *)ptr))
2174			return -EFAULT;
2175		ptr += sizeof(uint32_t);
2176		binder_stat_br(proc, thread, thread->return_error);
2177		thread->return_error = BR_OK;
2178		goto done;
2179	}
2180
2181
2182	thread->looper |= BINDER_LOOPER_STATE_WAITING;//进入waiting状态
2183	if (wait_for_proc_work)
2184		proc->ready_threads++;//可用binder_thread数+1
2185
2186	binder_unlock(__func__);
2187
2188	trace_binder_wait_for_work(wait_for_proc_work,
2189				   !!thread->transaction_stack,
2190				   !list_empty(&thread->todo));//trace
2191	if (wait_for_proc_work) {//如果当前binder thread 确实没有binder请求
2192		if (!(thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
2193					BINDER_LOOPER_STATE_ENTERED))) {//异常情况
2194			binder_user_error("%d:%d ERROR: Thread waiting for process work before calling BC_REGISTER_LOOPER or BC_ENTER_LOOPER (state %x)\n",
2195				proc->pid, thread->pid, thread->looper);
2196			wait_event_interruptible(binder_user_error_wait,
2197						 binder_stop_on_user_error < 2);
2198		}
2199		binder_set_nice(proc->default_priority);//设置优先级
2200		if (non_block) {//如果不需要block,则查看当前进程的binder_proc中是否有binder work需要做,如果没有,那么返回值为 -EAGAIN
2201			if (!binder_has_proc_work(proc, thread))
2202				ret = -EAGAIN;
2203		} else //如果需要block(一般走这个),则wait在这里,直到当前进程对应的binder_proc中有binder work(即有binder通信请求)
2204			ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));
2205	} else {//如果当前线程中存在 binder work需要做
2206		if (non_block) {
2207			if (!binder_has_thread_work(thread))
2208				ret = -EAGAIN;
2209		} else
2210			ret = wait_event_freezable(thread->wait, binder_has_thread_work(thread)); //再次根据thread是否有 binder work决定是否wait
2211	}
2212
2213	binder_lock(__func__);
2214
2215	if (wait_for_proc_work) //执行到这里说明不在wait,将要执行自己的binder work了,那么 read threads数量需要 -1
2216		proc->ready_threads--;
2217	thread->looper &= ~BINDER_LOOPER_STATE_WAITING; //把 waiting状态去掉
2218
2219	if (ret) //ret != 0
2220		return ret;
2221
2222	while (1) {
2223		uint32_t cmd;
2224		struct binder_transaction_data tr;
2225		struct binder_work *w;
2226		struct binder_transaction *t = NULL;
2227
2228		if (!list_empty(&thread->todo)) {
2229			w = list_first_entry(&thread->todo, struct binder_work,
2230					     entry); //取第一个binder work
2231		} else if (!list_empty(&proc->todo) && wait_for_proc_work) {
2232			w = list_first_entry(&proc->todo, struct binder_work,
2233					     entry);//binder thread中没有binder work,尝试从binder proc拿一个binder work
2234		} else {
2235			/* no data added */
2236			if (ptr - buffer == 4 &&
2237			    !(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN))//没有数据,重新尝试
2238				goto retry;
2239			break;
2240		}
2241
2242		if (end - ptr < sizeof(tr) + 4)//buffer剩余空间不足以存放一个{cmd, binder_transaction_data}数据对了
2243			break;
2244
2245		switch (w->type) {//binder work的type
2246		case BINDER_WORK_TRANSACTION: { //是个 transation
2247			t = container_of(w, struct binder_transaction, work); //获取对应 binder transation
2248		} break;
2249		case BINDER_WORK_TRANSACTION_COMPLETE: {
2250			cmd = BR_TRANSACTION_COMPLETE;
2251			if (put_user(cmd, (uint32_t __user *)ptr))//写入 cmd
2252				return -EFAULT;
2253			ptr += sizeof(uint32_t);
2254
2255			binder_stat_br(proc, thread, cmd);
2256			binder_debug(BINDER_DEBUG_TRANSACTION_COMPLETE,
2257				     "%d:%d BR_TRANSACTION_COMPLETE\n",
2258				     proc->pid, thread->pid);
2259
2260			list_del(&w->entry);//删除binder work
2261			kfree(w);
2262			binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE);
2263		} break;
2264		case BINDER_WORK_NODE: {
2265			struct binder_node *node = container_of(w, struct binder_node, work);
2266			uint32_t cmd = BR_NOOP;
2267			const char *cmd_name;
2268			int strong = node->internal_strong_refs || node->local_strong_refs;
2269			int weak = !hlist_empty(&node->refs) || node->local_weak_refs || strong;
2270
2271			if (weak && !node->has_weak_ref) {
2272				cmd = BR_INCREFS;
2273				cmd_name = "BR_INCREFS";
2274				node->has_weak_ref = 1;
2275				node->pending_weak_ref = 1;
2276				node->local_weak_refs++;
2277			} else if (strong && !node->has_strong_ref) {
2278				cmd = BR_ACQUIRE;
2279				cmd_name = "BR_ACQUIRE";
2280				node->has_strong_ref = 1;
2281				node->pending_strong_ref = 1;
2282				node->local_strong_refs++;
2283			} else if (!strong && node->has_strong_ref) {
2284				cmd = BR_RELEASE;
2285				cmd_name = "BR_RELEASE";
2286				node->has_strong_ref = 0;
2287			} else if (!weak && node->has_weak_ref) {
2288				cmd = BR_DECREFS;
2289				cmd_name = "BR_DECREFS";
2290				node->has_weak_ref = 0;
2291			}
2292			if (cmd != BR_NOOP) {
2293				if (put_user(cmd, (uint32_t __user *)ptr))
2294					return -EFAULT;
2295				ptr += sizeof(uint32_t);
2296				if (put_user(node->ptr,
2297					     (binder_uintptr_t __user *)ptr))
2298					return -EFAULT;
2299				ptr += sizeof(binder_uintptr_t);
2300				if (put_user(node->cookie,
2301					     (binder_uintptr_t __user *)ptr))
2302					return -EFAULT;
2303				ptr += sizeof(binder_uintptr_t);
2304
2305				binder_stat_br(proc, thread, cmd);
2306				binder_debug(BINDER_DEBUG_USER_REFS,
2307					     "%d:%d %s %d u%016llx c%016llx\n",
2308					     proc->pid, thread->pid, cmd_name,
2309					     node->debug_id,
2310					     (u64)node->ptr, (u64)node->cookie);
2311			} else {
2312				list_del_init(&w->entry);
2313				if (!weak && !strong) {
2314					binder_debug(BINDER_DEBUG_INTERNAL_REFS,
2315						     "%d:%d node %d u%016llx c%016llx deleted\n",
2316						     proc->pid, thread->pid,
2317						     node->debug_id,
2318						     (u64)node->ptr,
2319						     (u64)node->cookie);
2320					rb_erase(&node->rb_node, &proc->nodes);
2321					kfree(node);
2322					binder_stats_deleted(BINDER_STAT_NODE);
2323				} else {
2324					binder_debug(BINDER_DEBUG_INTERNAL_REFS,
2325						     "%d:%d node %d u%016llx c%016llx state unchanged\n",
2326						     proc->pid, thread->pid,
2327						     node->debug_id,
2328						     (u64)node->ptr,
2329						     (u64)node->cookie);
2330				}
2331			}
2332		} break;
2333		case BINDER_WORK_DEAD_BINDER:
2334		case BINDER_WORK_DEAD_BINDER_AND_CLEAR:
2335		case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: {
2336			struct binder_ref_death *death;
2337			uint32_t cmd;
2338
2339			death = container_of(w, struct binder_ref_death, work);
2340			if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION)
2341				cmd = BR_CLEAR_DEATH_NOTIFICATION_DONE;
2342			else
2343				cmd = BR_DEAD_BINDER;
2344			if (put_user(cmd, (uint32_t __user *)ptr))
2345				return -EFAULT;
2346			ptr += sizeof(uint32_t);
2347			if (put_user(death->cookie,
2348				     (binder_uintptr_t __user *)ptr))
2349				return -EFAULT;
2350			ptr += sizeof(binder_uintptr_t);
2351			binder_stat_br(proc, thread, cmd);
2352			binder_debug(BINDER_DEBUG_DEATH_NOTIFICATION,
2353				     "%d:%d %s %016llx\n",
2354				      proc->pid, thread->pid,
2355				      cmd == BR_DEAD_BINDER ?
2356				      "BR_DEAD_BINDER" :
2357				      "BR_CLEAR_DEATH_NOTIFICATION_DONE",
2358				      (u64)death->cookie);
2359
2360			if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION) {
2361				list_del(&w->entry);
2362				kfree(death);
2363				binder_stats_deleted(BINDER_STAT_DEATH);
2364			} else
2365				list_move(&w->entry, &proc->delivered_death);
2366			if (cmd == BR_DEAD_BINDER)
2367				goto done; /* DEAD_BINDER notifications can cause transactions */
2368		} break;
2369		}
2370
2371		if (!t)
2372			continue;
2373
2374		BUG_ON(t->buffer == NULL);
2375		if (t->buffer->target_node) {
2376			struct binder_node *target_node = t->buffer->target_node;
2377
2378			tr.target.ptr = target_node->ptr;
2379			tr.cookie =  target_node->cookie;
2380			t->saved_priority = task_nice(current);
2381			if (t->priority < target_node->min_priority &&
2382			    !(t->flags & TF_ONE_WAY))
2383				binder_set_nice(t->priority);
2384			else if (!(t->flags & TF_ONE_WAY) ||
2385				 t->saved_priority > target_node->min_priority)
2386				binder_set_nice(target_node->min_priority);
2387			cmd = BR_TRANSACTION;
2388		} else {
2389			tr.target.ptr = 0;
2390			tr.cookie = 0;
2391			cmd = BR_REPLY;
2392		}
2393		tr.code = t->code;
2394		tr.flags = t->flags;
2395		tr.sender_euid = from_kuid(current_user_ns(), t->sender_euid);
2396
2397		if (t->from) {
2398			struct task_struct *sender = t->from->proc->tsk;
2399
2400			tr.sender_pid = task_tgid_nr_ns(sender,
2401							task_active_pid_ns(current));
2402		} else {
2403			tr.sender_pid = 0;
2404		}
2405
2406		tr.data_size = t->buffer->data_size;
2407		tr.offsets_size = t->buffer->offsets_size;
2408		tr.data.ptr.buffer = (binder_uintptr_t)(
2409					(uintptr_t)t->buffer->data +
2410					proc->user_buffer_offset);
2411		tr.data.ptr.offsets = tr.data.ptr.buffer +
2412					ALIGN(t->buffer->data_size,
2413					    sizeof(void *));
2414
2415		if (put_user(cmd, (uint32_t __user *)ptr))
2416			return -EFAULT;
2417		ptr += sizeof(uint32_t);
2418		if (copy_to_user(ptr, &tr, sizeof(tr)))
2419			return -EFAULT;
2420		ptr += sizeof(tr);
2421
2422		trace_binder_transaction_received(t);
2423		binder_stat_br(proc, thread, cmd);
2424		binder_debug(BINDER_DEBUG_TRANSACTION,
2425			     "%d:%d %s %d %d:%d, cmd %d size %zd-%zd ptr %016llx-%016llx\n",
2426			     proc->pid, thread->pid,
2427			     (cmd == BR_TRANSACTION) ? "BR_TRANSACTION" :
2428			     "BR_REPLY",
2429			     t->debug_id, t->from ? t->from->proc->pid : 0,
2430			     t->from ? t->from->pid : 0, cmd,
2431			     t->buffer->data_size, t->buffer->offsets_size,
2432			     (u64)tr.data.ptr.buffer, (u64)tr.data.ptr.offsets);
2433
2434		list_del(&t->work.entry);
2435		t->buffer->allow_user_free = 1;
2436		if (cmd == BR_TRANSACTION && !(t->flags & TF_ONE_WAY)) {
2437			t->to_parent = thread->transaction_stack;
2438			t->to_thread = thread;
2439			thread->transaction_stack = t;
2440		} else {
2441			t->buffer->transaction = NULL;
2442			kfree(t);
2443			binder_stats_deleted(BINDER_STAT_TRANSACTION);
2444		}
2445		break;
2446	}
2447
2448done:
2449
2450	*consumed = ptr - buffer;
2451	if (proc->requested_threads + proc->ready_threads == 0 &&
2452	    proc->requested_threads_started < proc->max_threads &&
2453	    (thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
2454	     BINDER_LOOPER_STATE_ENTERED)) /* the user-space code fails to */
2455	     /*spawn a new thread if we leave this out */) {
2456		proc->requested_threads++;
2457		binder_debug(BINDER_DEBUG_THREADS,
2458			     "%d:%d BR_SPAWN_LOOPER\n",
2459			     proc->pid, thread->pid);
2460		if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer))
2461			return -EFAULT;
2462		binder_stat_br(proc, thread, BR_SPAWN_LOOPER);
2463	}
2464	return 0;
2465}

这个函数很长,但主要是因为case比较多,处理逻辑都写到这个函数了,其实可以把过长的case抽成函数的。。。

开始的时候,先往 buffer中写了一个 BR_NOOP:

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

代表啥事也不干,记下来占位的,方便后续替换为 BR_SPAWN_LOOPER;

 

这里大体说下函数作用:

  1. 先尝试从 binder thread 中拿 binder work来做
  2. 如果binder thread中没有binder work需要做,那么尝试从 binder_proc中找 binder work来做
  3. 如果都找不到 binder work,那么当前线程进入等待,并基数 proc->thread_ready +1
  4. 找到binder work后,找到其cmd,target_node 及binder_transaction_data,然后依次拷贝到用户空间的 read buffer
  5. 完成后,更新 bwr.read_consumed以便用户空间知道读取到多少数据

这里有一点的还没弄清楚的是,binder work中如何记录数据的,不过没有关系,我们后续分析binder请求的创建的时候会弄明白的,现在只需要知道我们把binder请求数据已经读取到了 service manager进程的read buffer中即可。

那么读取到数据后,接下来就应该是解析数据了,再摘抄部分binder_looper代码:

406        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);//此时这个函数已经返回
407
408        if (res < 0) {
409            ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
410            break;
411        }
412        //接下来将要执行 binder_parse,看到,确实用到了 bwr.read_consumed
413        res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);

接下来调用 binder_parse:

216int binder_parse(struct binder_state *bs, struct binder_io *bio,
217                 uintptr_t ptr, size_t size, binder_handler func)
218{
219    int r = 1;
220    uintptr_t end = ptr + (uintptr_t) size;//read buffer中有效数据末尾
221
222    while (ptr < end) {
223        uint32_t cmd = *(uint32_t *) ptr;//读取一个 cmd
224        ptr += sizeof(uint32_t);//更新 ptr
225#if TRACE
226        fprintf(stderr,"%s:\n", cmd_name(cmd));
227#endif
228        switch(cmd) {
229        case BR_NOOP:
230            break;
231        case BR_TRANSACTION_COMPLETE:
232            break;
233        case BR_INCREFS:
234        case BR_ACQUIRE:
235        case BR_RELEASE:
236        case BR_DECREFS:
237#if TRACE
238            fprintf(stderr,"  %p, %p\n", (void *)ptr, (void *)(ptr + sizeof(void *)));
239#endif
240            ptr += sizeof(struct binder_ptr_cookie);
241            break;
242        case BR_TRANSACTION: {//一个 transaction事物,主要是这个
243            struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
244            if ((end - ptr) < sizeof(*txn)) {//数据合法性检测
245                ALOGE("parse: txn too small!\n");
246                return -1;
247            }
248            binder_dump_txn(txn);
249            if (func) {//有处理函数,这里是 srvcmgr_handler
250                unsigned rdata[256/4];
251                struct binder_io msg;
252                struct binder_io reply;
253                int res;
254
255                bio_init(&reply, rdata, sizeof(rdata), 4);
256                bio_init_from_txn(&msg, txn);
257                res = func(bs, txn, &msg, &reply);//srvcmr_handler处理
258                if (txn->flags & TF_ONE_WAY) { //one way处理buffer
259                    binder_free_buffer(bs, txn->data.ptr.buffer);
260                } else {// 非one way,要发送reply
261                    binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
262                }
263            }
264            ptr += sizeof(*txn);
265            break;
266        }
267        case BR_REPLY: {
268            struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
269            if ((end - ptr) < sizeof(*txn)) {
270                ALOGE("parse: reply too small!\n");
271                return -1;
272            }
273            binder_dump_txn(txn);
274            if (bio) {
275                bio_init_from_txn(bio, txn);
276                bio = 0;
277            } else {
278                /* todo FREE BUFFER */
279            }
280            ptr += sizeof(*txn);
281            r = 0;
282            break;
283        }
284        case BR_DEAD_BINDER: {//death处理
285            struct binder_death *death = (struct binder_death *)(uintptr_t) *(binder_uintptr_t *)ptr;
286            ptr += sizeof(binder_uintptr_t);
287            death->func(bs, death->ptr);
288            break;
289        }
290        case BR_FAILED_REPLY:
291            r = -1;
292            break;
293        case BR_DEAD_REPLY:
294            r = -1;
295            break;
296        default:
297            ALOGE("parse: OOPS %d\n", cmd);
298            return -1;
299        }
300    }
301
302    return r;
303}

这个函数里,我们主要看 BINDER_TRANSACTION 这个 cmd,这里会从 read buffer中读出一个binder_transaction_data数据 txn,txn的读取:

然后构建两个binder_io数据,跳转到 srvcmgr_handler处理这个 cmd。

这里看下 binder_io是什么:

12struct binder_io
13{
14    char *data;            /* pointer to read/write from */
15    binder_size_t *offs;   /* array of offsets */
16    size_t data_avail;     /* bytes available in data buffer */
17    size_t offs_avail;     /* entries available in offsets array */
18
19    char *data0;           /* start of data buffer */
20    binder_size_t *offs0;  /* start of offsets buffer */
21    uint32_t flags;
22    uint32_t unused;
23};

前面执行到这里代码:

250                unsigned rdata[256/4];
252                struct binder_io reply;
255                bio_init(&reply, rdata, sizeof(rdata), 4);

看下bio_init如何做的:

434void bio_init(struct binder_io *bio, void *data,
435              size_t maxdata, size_t maxoffs)
436{
437    size_t n = maxoffs * sizeof(size_t); // n = 4*4 =16
438
439    if (n > maxdata) {
440        bio->flags = BIO_F_OVERFLOW;
441        bio->data_avail = 0;
442        bio->offs_avail = 0;
443        return;
444    }
445
446    bio->data = bio->data0 = (char *) data + n; //rdata+4
447    bio->offs = bio->offs0 = data; //rdata
448    bio->data_avail = maxdata - n; //256-16
449    bio->offs_avail = maxoffs; // 4
450    bio->flags = 0;
451}

所以此时 reply:

243            struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
251                struct binder_io msg;
256                bio_init_from_txn(&msg, txn);

binder_transaction_data:

96struct binder_transaction_data {
97  union {
99    __u32 handle;
100    binder_uintptr_t ptr;
101  } target;
102  binder_uintptr_t cookie;
104  __u32 code;
105  __u32 flags;
106  pid_t sender_pid;
107  uid_t sender_euid;
109  binder_size_t data_size;
110  binder_size_t offsets_size;
111  union {
112    struct {
114      binder_uintptr_t buffer;
115      binder_uintptr_t offsets;
116    } ptr;
117    __u8 buf[8];
119  } data;
120};
425void bio_init_from_txn(struct binder_io *bio, struct binder_transaction_data *txn)
426{
427    bio->data = bio->data0 = (char *)(intptr_t)txn->data.ptr.buffer;
428    bio->offs = bio->offs0 = (binder_size_t *)(intptr_t)txn->data.ptr.offsets;
429    bio->data_avail = txn->data_size;
430    bio->offs_avail = txn->offsets_size / sizeof(size_t);
431    bio->flags = BIO_F_SHARED;
432}

此时的 msg:


 

三个参数准备好后,接下来继续执行

257                res = func(bs, txn, &msg, &reply);//srvcmr_handler处理

func就是 svcmgr_handler:

262int svcmgr_handler(struct binder_state *bs,
263                   struct binder_transaction_data *txn,
264                   struct binder_io *msg,
265                   struct binder_io *reply)
266{
267    struct svcinfo *si;
268    uint16_t *s;
269    size_t len;
270    uint32_t handle;
271    uint32_t strict_policy;
272    int allow_isolated;
273
274    //ALOGI("target=%p code=%d pid=%d uid=%d\n",
275    //      (void*) txn->target.ptr, txn->code, txn->sender_pid, txn->sender_euid);
276
277    if (txn->target.ptr != BINDER_SERVICE_MANAGER)
278        return -1;
279
280    if (txn->code == PING_TRANSACTION)
281        return 0;
282
283    // Equivalent to Parcel::enforceInterface(), reading the RPC
284    // header with the strict mode policy mask and the interface name.
285    // Note that we ignore the strict_policy and don't propagate it
286    // further (since we do no outbound RPCs anyway).
287    strict_policy = bio_get_uint32(msg);
288    s = bio_get_string16(msg, &len);
289    if (s == NULL) {
290        return -1;
291    }
292
293    if ((len != (sizeof(svcmgr_id) / 2)) ||
294        memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
295        fprintf(stderr,"invalid id %s\n", str8(s, len));
296        return -1;
297    }
298
299    if (sehandle && selinux_status_updated() > 0) {
300        struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle();
301        if (tmp_sehandle) {
302            selabel_close(sehandle);
303            sehandle = tmp_sehandle;
304        }
305    }
306
307    switch(txn->code) {
308    case SVC_MGR_GET_SERVICE:
309    case SVC_MGR_CHECK_SERVICE:
310        s = bio_get_string16(msg, &len);
311        if (s == NULL) {
312            return -1;
313        }
314        handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid);
315        if (!handle)
316            break;
317        bio_put_ref(reply, handle);
318        return 0;
319
320    case SVC_MGR_ADD_SERVICE:
321        s = bio_get_string16(msg, &len);
322        if (s == NULL) {
323            return -1;
324        }
325        handle = bio_get_ref(msg);
326        allow_isolated = bio_get_uint32(msg) ? 1 : 0;
327        if (do_add_service(bs, s, len, handle, txn->sender_euid,
328            allow_isolated, txn->sender_pid))
329            return -1;
330        break;
331
332    case SVC_MGR_LIST_SERVICES: {
333        uint32_t n = bio_get_uint32(msg);
334
335        if (!svc_can_list(txn->sender_pid, txn->sender_euid)) {
336            ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
337                    txn->sender_euid);
338            return -1;
339        }
340        si = svclist;
341        while ((n-- > 0) && si)
342            si = si->next;
343        if (si) {
344            bio_put_string16(reply, si->name);
345            return 0;
346        }
347        return -1;
348    }
349    default:
350        ALOGE("unknown code %d\n", txn->code);
351        return -1;
352    }
353
354    bio_put_uint32(reply, 0);
355    return 0;
356}

这个时候相当于已经从 readbuf中读到请求,然后执行这些请求,比如 addService请求等。

至此,我们已经分析完成如下:

  1. service manager 进程如何与binder driver共享物理内存,即一次拷贝通信的基石
  2. service manager 如何成功所有service 管理者的
  3. service manager 如何读取binder请求,读取完后由 srvcmgr_handler处理

后续我们将在其他文章继续分析 service 的查找和添加的实现。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值