Binder从陌生到熟悉(中)

945 阅读20分钟

Binder从陌生到熟悉(上)

Binder从陌生到熟悉(下)

源码

*以下源码基于Android 6.0

1. Binder驱动

  • 1.1 binder_init
kernel/drivers/staging/android/binder.c

//4290  设备驱动入口函数
device_initcall(binder_init);
//4213
static int __init binder_init(void)
{
...
	//创建名为binder的单线程工作队列
	binder_deferred_workqueue = create_singlethread_workqueue("binder");
...
	strcpy(device_names, binder_devices_param);

	while ((device_name = strsep(&device_names, ","))) {
		//初始化设备
		ret = init_binder_device(device_name);
		if (ret)
			goto err_init_binder_device_failed;
	}

	return ret;

...
}

1.1.1 init_binder_device

kernel/drivers/staging/android/binder.c

//4186
static int __init init_binder_device(const char *name)
{
	int ret;
	struct binder_device *binder_device;

	//为binder设备分配内存
	binder_device = kzalloc(sizeof(*binder_device), GFP_KERNEL);
	if (!binder_device)
		return -ENOMEM;
	//初始化设备
	//设备的文件操作结构是binder_fops结构体
	binder_device->miscdev.fops = &binder_fops;
	//次设备号,动态分配
	binder_device->miscdev.minor = MISC_DYNAMIC_MINOR;
	//设备名称为binder
	binder_device->miscdev.name = name;

	binder_device->context.binder_context_mgr_uid = INVALID_UID;
	binder_device->context.name = name;

	//misc设备注册
	ret = misc_register(&binder_device->miscdev);
	if (ret < 0) {
		kfree(binder_device);
		return ret;
	}
	// 将hlist节点添加到binder_devices为表头的设备链表
	hlist_add_head(&binder_device->hlist, &binder_devices);

	return ret;
}

1.给binder驱动设备分配内存

2.初始化binder驱动

3.放入设备链表

  • 1.2 binder_open
kernel/drivers/staging/android/binder.c

//3454
static int binder_open(struct inode *nodp, struct file *filp)
{
	struct binder_proc *proc;
	struct binder_device *binder_dev;

	binder_debug(BINDER_DEBUG_OPEN_CLOSE, "binder_open: %d:%d\n",
		     current->group_leader->pid, current->pid);
	//给binder_proc结构体在内核分配内存空间
	proc = kzalloc(sizeof(*proc), GFP_KERNEL);
	if (proc == NULL)
		return -ENOMEM;
	//将当前线程的task保存到binder进程的task,增加task引用计数
	get_task_struct(current);
	proc->tsk = current;
	//初始化todo列表,用于存放待处理的请求(Server端)
	INIT_LIST_HEAD(&proc->todo);
	//初始化wait队列,这个队列用于等待返回结果(client端)或者等待请求(server端)
	init_waitqueue_head(&proc->wait);
	//将当前进程的nice值转化为进程优先级
	proc->default_priority = task_nice(current);
	binder_dev = container_of(filp->private_data, struct binder_device,
				  miscdev);
	proc->context = &binder_dev->context;
	//加一个同步锁,因为binder支持多线程访问
	binder_lock(__func__);
	//类型为BINDER_STAT_PROC对象创建数+1
	binder_stats_created(BINDER_STAT_PROC);
	//将proc_node节点添加到binder_procs队列头部
	hlist_add_head(&proc->proc_node, &binder_procs);
	//进程pid
	proc->pid = current->group_leader->pid;
	//初始化已分发的死亡通知列表
	INIT_LIST_HEAD(&proc->delivered_death);
	//将这个binder_proc与filp关联,这样通过filp就能找到这个proc,以便于在之后的mmap、ioctl中获取
	filp->private_data = proc;
	//释放同步锁
	binder_unlock(__func__);
    
...

	return 0;
}

1.创建binder_proc结构体实例proc

2.把当前的进程信息保存到proc实例中

3.将binder_proc链入binder_procs哈希链表中

4.将初始化好的proc,存放到filp->private_data中,以便后续使用

  • 1.3 binder_mmap
kernel/drivers/staging/android/binder.c

//3355
static int binder_mmap(struct file *filp, struct vm_area_struct *vma/*用户态虚拟地址空间描述,地址空间在0~3G*/)
{
	int ret;
	//一块连续的内核虚拟地址空间描述,32位体系架构中地址空间在 3G+896M + 8M ~ 4G之间
	struct vm_struct *area;
	struct binder_proc *proc = filp->private_data;
	const char *failure_string;
	struct binder_buffer *buffer;

	if (proc->tsk != current)
		return -EINVAL;
	//保证映射的内存大小不超过4M,如果大于4M就改为4M大小
	if ((vma->vm_end - vma->vm_start) > SZ_4M)
		vma->vm_end = vma->vm_start + SZ_4M;

...

	//加上binder_mmap_lock互斥锁,因为接下来要操作proc结构体,可能发生多线程竞争,保证一次只有一个进程分配内存,保证多进程之间的并发访问
	mutex_lock(&binder_mmap_lock);
	//是否已经做过映射,执行过则进入if,goto跳转,释放同步锁后结束binder_mmap函数
	if (proc->buffer) {
		ret = -EBUSY;
		failure_string = "already mapped";
		goto err_already_mapped;
	}
	//采用VM_IOREMAP方式分配一块连续的内核虚拟地址空间,与进程虚拟地址空间大小一致,注意虚拟地址空间是在此一次性分配的,物理页面却是需要时才去申请和映射
	area = get_vm_area(vma->vm_end - vma->vm_start, VM_IOREMAP);
	//内存分配不成功报错
	if (area == NULL) {
		ret = -ENOMEM;
		failure_string = "get_vm_area";
		goto err_get_vm_area_failed;
	}
	//将内核虚拟地址记录在proc的buffer中 
	proc->buffer = area->addr;
	//计算用户空间和内核空间的地址偏移量,地址偏移量=用户空间虚拟内存地址-内核空间虚拟内存地址
	proc->user_buffer_offset = vma->vm_start - (uintptr_t)proc->buffer;
	//释放锁
	mutex_unlock(&binder_mmap_lock);

...

	//分配物理页的指针数组,数组大小为vma的等效page页数
	proc->pages = kzalloc(sizeof(proc->pages[0]) * ((vma->vm_end - vma->vm_start) / PAGE_SIZE), GFP_KERNEL);
	if (proc->pages == NULL) {
		ret = -ENOMEM;
		failure_string = "alloc page array";
		goto err_alloc_pages_failed;
	}
	proc->buffer_size = vma->vm_end - vma->vm_start;

	vma->vm_ops = &binder_vm_ops;
	vma->vm_private_data = proc;

	//分配物理页面,同时映射到内核空间和用户进程空间,先分配1个物理页
	if (binder_update_page_range(proc, 1, proc->buffer, proc->buffer + PAGE_SIZE, vma)) {
		ret = -ENOMEM;
		failure_string = "alloc small buf";
		goto err_alloc_small_buf_failed;
	}
	buffer = proc->buffer;
	INIT_LIST_HEAD(&proc->buffers);
	//将buffer连入buffers链表中
	list_add(&buffer->entry, &proc->buffers);
	//此内存可用
	buffer->free = 1;
	//将内核虚拟内存buffer链入proc的buffers和free_buffers链表中
	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;

	/*pr_info("binder_mmap: %d %lx-%lx maps %p\n",
		 proc->pid, vma->vm_start, vma->vm_end, proc->buffer);*/
	return 0;

...
}

1.3.1 binder_update_page_range

kernel/drivers/staging/android/binder.c

//576
static int binder_update_page_range(struct binder_proc *proc, int allocate,
				    void *start, void *end,
				    struct vm_area_struct *vma)
{
	void *page_addr;
	unsigned long user_page_addr;
	struct page **page;
	struct mm_struct *mm;
    
...
    
	//allocate=1,代表分配内存过程,allocate=0代表释放内存过程
	if (allocate == 0)
		goto free_range;

...
    
		//分配1个page的物理内存
		*page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO);
...
    
		//物理空间映射到虚拟内核空间
		ret = map_kernel_range_noflush((unsigned long)page_addr,
					PAGE_SIZE, PAGE_KERNEL, page);
...
    
		//物理空间映射到虚拟进程空间
		ret = vm_insert_page(vma, user_page_addr, page[0]);
...

}

1.3.2 binder_insert_free_buffer

kernel/drivers/staging/android/binder.c

//494
static void binder_insert_free_buffer(struct binder_proc *proc,
				      struct binder_buffer *new_buffer)
{
	struct rb_node **p = &proc->free_buffers.rb_node;
	struct rb_node *parent = NULL;
	struct binder_buffer *buffer;
	size_t buffer_size;
	size_t new_buffer_size;

...

	while (*p) {
		parent = *p;
		buffer = rb_entry(parent, struct binder_buffer, rb_node);
		BUG_ON(!buffer->free);
		//计算出空闲内存的大小
		buffer_size = binder_buffer_size(proc, buffer);

		if (new_buffer_size < buffer_size)
			p = &parent->rb_left;
		else
			p = &parent->rb_right;
	}
	rb_link_node(&new_buffer->rb_node, parent, p);
	//将buffer插入到proc->free_buffers链表中
	rb_insert_color(&new_buffer->rb_node, &proc->free_buffers);
}

1.通过用户空间的虚拟内存大小,分配一块内核空间的虚拟内存

2.分配一块4kb(1页)的物理内存

3.把这块物理内存分别映射到用户空间的虚拟内存和内核空间的虚拟内存

  • 1.4 binder_ioctl
 kernel/drivers/staging/android/binder.c

//3241
static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	int ret;
	struct binder_proc *proc = filp->private_data;
	struct binder_thread *thread;
	//读取命令的大小
	unsigned int size = _IOC_SIZE(cmd);
	void __user *ubuf = (void __user *)arg;

	/*pr_info("binder_ioctl: %d:%d %x %lx\n",
			proc->pid, current->pid, cmd, arg);*/

	trace_binder_ioctl(cmd, arg);
	//进入休眠状态,直到中断唤醒
	//如果binder_stop_on_user_error < 2 则直接返回0;否则,调用_wait_event_interruptible进入可中断的挂起状态,接着让出处理器,
	//直到被wake_up且条件(binder_stop_on_user_error < 2)为真时才返回
	ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
	if (ret)
		goto err_unlocked;
	//获取binder_main_lock锁
	binder_lock(__func__);
	//根据当前进程的pid,从binder_proc中查找binder_thread,如果当前线程已经加入到proc的线程队列,则直接返回,
	//如果不存在,则创建binder_thread,然后将当前线程添加到当前的proc
	thread = binder_get_thread(proc);
	if (thread == NULL) {
		ret = -ENOMEM;
		goto err;
	}

	switch (cmd) {
		//读写命令,数据传输,binder IPC通信的核心逻辑
	case BINDER_WRITE_READ:
		ret = binder_ioctl_write_read(filp, cmd, arg, thread);
		if (ret)
			goto err;
		break;
		//设置最大线程数,直接将值设置到proc结构的max_threads域中
		if (copy_from_user(&proc->max_threads, ubuf, sizeof(proc->max_threads))) {
			ret = -EINVAL;
			goto err;
		}
		break;
		//设置Context manager,即将自己设置为ServiceManager
	case BINDER_SET_CONTEXT_MGR:
		ret = binder_ioctl_set_ctx_mgr(filp);
		if (ret)
			goto err;
		break;
		//binder线程退出命令,释放相关资源
	case BINDER_THREAD_EXIT:
		binder_debug(BINDER_DEBUG_THREADS, "%d:%d exit\n",
			     proc->pid, thread->pid);
		binder_free_thread(proc, thread);
		thread = NULL;
		break;
		//获取binder驱动版本号,在kernel4.4版本中,32位该值为7,64位版本该值为8
	case BINDER_VERSION: {
		struct binder_version __user *ver = ubuf;

		if (size != sizeof(struct binder_version)) {
			ret = -EINVAL;
			goto err;
		}
		if (put_user(BINDER_CURRENT_PROTOCOL_VERSION,
			     &ver->protocol_version)) {
			ret = -EINVAL;
			goto err;
		}
		break;
	}
	default:
		ret = -EINVAL;
		goto err;
	}
	ret = 0;
err:
	if (thread)
		thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN;
	binder_unlock(__func__);
	wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
	if (ret && ret != -ERESTARTSYS)
		pr_info("%d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
err_unlocked:
	trace_binder_ioctl_done(ret);
	return ret;
}

1.4.1 binder_ioctl_write_read

kernel/drivers/staging/android/binder.c

//3136
static int binder_ioctl_write_read(struct file *filp,
				unsigned int cmd, unsigned long arg,
				struct binder_thread *thread)
{
	int ret = 0;
	struct binder_proc *proc = filp->private_data;
	//读取arg的大小
	unsigned int size = _IOC_SIZE(cmd);
	void __user *ubuf = (void __user *)arg;
	struct binder_write_read bwr;

	if (size != sizeof(struct binder_write_read)) {
		ret = -EINVAL;
		goto out;
	}
	//把用户空间数据ubuf拷贝到内核空间bwr
	if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {
		ret = -EFAULT;
		goto out;
	}
	binder_debug(BINDER_DEBUG_READ_WRITE,
		     "%d:%d write %lld at %016llx, read %lld at %016llx\n",
		     proc->pid, thread->pid,
		     (u64)bwr.write_size, (u64)bwr.write_buffer,
		     (u64)bwr.read_size, (u64)bwr.read_buffer);
	//表示用户进程有数据发送到驱动,执行binder_thread_write发送数据
	if (bwr.write_size > 0) {
		ret = binder_thread_write(proc, thread,
					  bwr.write_buffer,
					  bwr.write_size,
					  &bwr.write_consumed);
		trace_binder_write_done(ret);
		if (ret < 0) {
			//binder_thread_write中有错误发生,则read_consumed设为0,表示kernel没有数据返回给进程
			bwr.read_consumed = 0;
			//将bwr返回给用户态调用者,bwr在binder_thread_write中会被修改
			if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
				ret = -EFAULT;
			goto out;
		}
	}
	//表示进程用户态地址空间希望有数据返回给它,则调用binder_thread_read进行处理
	if (bwr.read_size > 0) {
		ret = binder_thread_read(proc, thread, bwr.read_buffer,
					 bwr.read_size,
					 &bwr.read_consumed,
					 filp->f_flags & O_NONBLOCK);
		trace_binder_read_done(ret);
		//进程todo队列不为空,唤醒该队列中的线程
		if (!list_empty(&proc->todo))
			wake_up_interruptible(&proc->wait);
		if (ret < 0) {
			if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
				ret = -EFAULT;
			goto out;
		}
	}
	binder_debug(BINDER_DEBUG_READ_WRITE,
		     "%d:%d wrote %lld of %lld, read return %lld of %lld\n",
		     proc->pid, thread->pid,
		     (u64)bwr.write_consumed, (u64)bwr.write_size,
		     (u64)bwr.read_consumed, (u64)bwr.read_size);
	//把内核空间的数据bwr拷贝到用户空间ubuf
	if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
		ret = -EFAULT;
		goto out;
	}
out:
	return ret;
}

Binder驱动没有提供read/write操作,所有数据传输、控制都是通过binder_ioctl进行,因此该部分是Binder驱动的核心内容,承载了Binder数据传输部分的主要业务,在Binder IPC机制通信的时候,主要执行BINDER_WRITE_READ命令进行数据传输

  • 1.5 主要的数据结构体

1.5.1file_operations定义了文件操作符与Binder驱动的对应函数关联

static const struct file_operations binder_fops = {
	.owner = THIS_MODULE,
	.poll = binder_poll,
	.unlocked_ioctl = binder_ioctl,//64位的应用运行在64位的内核或者32位的应用运行在32位的内核上时调用
	.compat_ioctl = binder_ioctl,//32位的应用运行在64位的内核上时调用
	.mmap = binder_mmap,//用户空间的mmap()操作,会引起Binder驱动的binder_mmap()函数的调用
	.open = binder_open,//用户空间的open()操作,会引起Binder驱动的binder_open()函数的调用
	.flush = binder_flush,
	.release = binder_release,
};

1.5.2 binder_proc 代表的是一个正在使用Binder进程通信的进程,binder_proc为管理其信息的记录体,当一个进程open /dev/binder 时,Binder驱动程序会为其创建一个binder_proc结构体,用以记录进程的所有相关信息,并把该结构体保存到一个全局的hash表中

kernel/drivers/staging/android/binder.c

//322
struct binder_proc {
	struct hlist_node proc_node;//进程节点
	struct rb_root threads;//binder_thread红黑树的根节点
	struct rb_root nodes;//binder_node红黑树的根节点 关键字 ptr
	struct rb_root refs_by_desc;//binder_ref红黑树的根节点(以handle为key)关键字  desc
	struct rb_root refs_by_node;//binder_ref红黑树的根节点(以ptr为key)关键字  node
	int pid;//进程ID
	struct vm_area_struct *vma; // 指向进程虚拟地址空间的指针
	struct mm_struct *vma_vm_mm; // 进程的整个虚拟地址空间
	struct task_struct *tsk; //     相应进程的 task结构体 任务控制模块
	struct files_struct *files; // 相应进程的 文件结构体数组
	struct hlist_node deferred_work_node;
	int deferred_work;
	void *buffer; // 内核空间的起始地址
	ptrdiff_t user_buffer_offset;// 内核空间与用户空间的地址偏移量

	struct list_head buffers;// 所有的 buffer
	struct rb_root free_buffers;// 空闲的 buffer
	struct rb_root allocated_buffers;//可分配的 buffer
	size_t free_async_space;//异步的可用空闲空间大小

	struct page **pages;// 指向物理内存页的指针
	size_t buffer_size;// 映射的内核空间大小
	uint32_t buffer_free;// 可用内存总大小
	struct list_head todo; // 进程将要做的事
	wait_queue_head_t wait; // 等待队列
	struct binder_stats stats;// binder统计信息
	struct list_head delivered_death; // 已分发的死亡通知
	int max_threads; // 最大线程数
	int requested_threads; // 请求的线程数
	int requested_threads_started; // 已启动的请求线程数
	int ready_threads; // 准备就绪的线程个数
	long default_priority; // 默认优先级
	struct dentry *debugfs_entry;
	struct binder_context *context;// 连接 存储binder_node和binder_context_mgr_uid以及name
};

1.5.3 binder_node 代表的是Binder实体对象,每一个service组件或者ServiceManagerBinder驱动程序中的描述,Binder驱动通过强引用和弱引用来维护其生命周期,通过node找到空间的Service对象.

kernel/drivers/staging/android/binder.c

//252
struct binder_node {
	int debug_id; // 节点创建时分配,具有全局唯一性,用于调试使用
	struct binder_work work;
	 /** 每一个binder进程都由一个binder_proc来描述,binder进程内部所有Binder实体对象,
        由一个红黑树来进行组织(struct rb_root nodes)  ; rb_node 则对应nodes的一个节点 */
	union {
		struct rb_node rb_node; // binder节点正常使用,union 用于本节点连接红黑树
		  // 如果Binder 实体对象对应的进程死亡,销毁节点时需要将rb_node从红黑树中删除,
        //如果本节点还没有引用切断,则用dead_node将其隔离到另一个链表中,
        //直到通知所有进程切断与该节点的引用后,该节点才能销毁
		struct hlist_node dead_node;// binder节点已销毁,union
	};
	struct binder_proc *proc; // 指向该Binder实体对象 对应的进程,进程由binder_proc描述
	 // 该 Binder实体对象可能同时被多个Client组件引用,所有指向本实体对象的引用都
    //保存在这个hash队列中refs表示队列头部;这些引用可能隶属于不同进程,遍历该
    //hash表能够得到这些Client组件引用了这些对象
	struct hlist_head refs; // 所有指向该节点的 binder引用队列

	/** 引用计数 
     * 1、当一个Binder实体对象请求一个Service组件来执行Binder操作时。会增加该Service
     * 组件的强/弱引用计数同时,Binder实体对象将会has_strong_ref与has_weak_ref置为1 
     *2、当一个Service组件完成一个Binder实体对象请求的操作后,Binder对象会请求减少该
     * Service组件的强/弱引用计数
     * 3、Binder实体对象在请求一个Service组件增加或减少强/弱引用计数的过程中,
     * 会将pending_strong_ref和pending_weak_ref置为1,当Service组件完成增加
     * 或减少计数时,Binder实体对象会将这两个变量置为0
     */
	int internal_strong_refs;//远程强引用 计数 实际上代表了一个binder_node与多少个binder_ref相关联
	int local_weak_refs;//本地弱引用技数
	int local_strong_refs; //本地强引用计数
	binder_uintptr_t ptr; // 指向用户空间 binder_node的指针,对应于 flat_binder_object.binder 描述用户空间的Service组件,对应Binder实体对应的Service在用户空间的(BBinder)的引用
	binder_uintptr_t cookie;// 指向用户空间 binder_node的指针,附件数据,对应于 flat_binder_object.cookie 描述用户空间的Service组件,Binder实体对应的Service在用户空间的本地Binder(BBinder)地址
	unsigned has_strong_ref:1;// 占位 1bit
	unsigned pending_strong_ref:1;// 占位 1bit
	unsigned has_weak_ref:1;// 占位 1bit
	unsigned pending_weak_ref:1;// 占位 1bit
	unsigned has_async_transaction:1;// 占位 1bit
	 // 表示该Binder实体对象能否接收含有该文件描述符的进程间通信数据。当一个进程向
    //另一个进程发送数据中包含文件描述符时,Binder会在目标进程中打开一个相同的文件
    //故设为accept_fds为0 可以防止源进程在目标进程中打开文件
	unsigned accept_fds:1;// 占位 1bit
	unsigned min_priority:8;// 占位 8bit 处理Binder请求的线程最低优先级
	struct list_head async_todo;//异步todo队列
};

binder_procbinder_node关系: 可以将binder_proc理解为一个进程,而将binder_noder理解为一个Servicebinder_proc里面有一个红黑树,用来保存所有在它所描述的进程里面创建Service。而每一个ServiceBinder驱动里面都有一个binder_node来描述。

async_todo,步事务处理,目的在于为同步交互让路,避免长时间阻塞发送送端

异步事务定义:(相对于同步事务)单向进程间通信要求,即不需要等待应答的进程间通信请求 Binder驱动程序认为异步事务的优先级低于同步事务,则在同一时刻,一个Binder实体对象至多只有一个异步事物会得到处理。而同步事务则无此限制。 Binder将事务保存在一个线程binder_threadtodo队列中,表示由该线程来处理该事务。每一个事务都关联Binder实体对象(union target),表示该事务的目标处理对象,表示要求该Binder实体对象对应的Service组件在指定线程中处理该事务,而如果Binder发现一个事务是异步事务,则会将其保存在目标Binder对象的async_todo的异步事务中等待处理

1.5.4 binder_buffer 内核缓冲区,用以在进程间传递数据。binder驱动程序管理这个内存映射地址空间方法,即管理buffer~(buffer+buffer_size)这段地址空间的,这个地址空间被划分为一段一段来管理,每一段是结构体struct binder_buffer来描述。每一个binder_buffer通过其成员entry从低到高地址连入到struct binder_proc中的buffers表示链表中去

kernel/drivers/staging/android/binder.c

//298
struct binder_buffer {
	struct list_head entry; //buffer实体的地址 对应内核缓冲区列表的buffers(内核缓冲区列表)
	struct rb_node rb_node;  // buffer实体的地址 结合free,如果free=1,则rb_node对应free_buffers中一个节点(内核缓冲区) 如果free!=1,则对应allocated_buffers中的一个节点
				/* by address */
	unsigned free:1; // 标记是否是空闲buffer,占位1bit
	 /**Binder将事务数据保存到一个内核缓冲区(binder_transaction.buffer),然后交由Binder
      * 实体对象(target_node) 处理,而target_node会将缓冲区的内容交给对应的Service组件
      * (proc) 来处理,Service组件处理完事务后,若allow_user_free=1,则请求Binder释放该
      * 内核缓冲区
      */
	unsigned allow_user_free:1;// 是否允许用户释放,占位1bit
	unsigned async_transaction:1; // 占位1bit 表示事务是异步的;异步事务的内核缓冲区大小是受限的,这样可以保证事务可以优先放到缓冲区
	unsigned debug_id:29; // 占位29bit

	struct binder_transaction *transaction; // 该缓存区的需要处理的事务 用以中转请求和返回结果

	struct binder_node *target_node; // 该缓存区所需处理的Binder实体
	/** 
     *  存储通信数据,通信数据中有两种类型数据:普通数据与Binder对象
     *  在数据缓冲区最后,有一个偏移数组,记录数据缓冲区中每一个Binder
     *  对象在缓冲区的偏移地址
     */
	size_t data_size;// 数据缓冲区大小
	size_t offsets_size;// 数据偏移量(其实也是偏移位置)
	size_t extra_buffers_size;//额外缓冲区大小
	uint8_t data[0]; // 数据地址 用以保存通信数据,数据缓冲区,大小可变
};

2. ServiceManager

ServiceManager是由Android系统启动时,init进程通过解析init.rc文件而创建的,其所对应的可执行程序servicemanager, 所对应的源文件是service_manager.c,进程名为servicemanager。 在ServiceManager中有两个比较重要的方法:add_servicecheck_service,系统的service需要通过add_service把自己的信息注册到servicemanager中,当需要使用时,通过check_service检查该service是否存在

  • 如何启动ServiceManager

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

2.1 main

frameworks/native/cmds/servicemanager/service_manager.c

//354
int main(int argc, char **argv)
{
    struct binder_state *bs;
    // 打开 binder驱动,申请 128k字节大小的内存空间
    bs = (128*1024);
...
    //设为守护进程,成为 binder的管理者
    if (binder_become_context_manager(bs)) {
        ALOGE("cannot become context manager (%s)\n", strerror(errno));
        return -1;
    }
...
    //进入无限循环,处理client端发来的请求
    binder_loop(bs, svcmgr_handler);

    return 0;
}

mian()方法中主要做了三件事:

  • 2.1.1 binder_open 打开 binder驱动,申请 128k字节大小的内存空间

但是这个binder_open并不是我们上面binder驱动中的binder_open,这个是native层中的

frameworks/native/cmds/servicemanager/binder.c

//96
struct binder_state *binder_open(size_t mapsize)
{
    // 这个结构体记录了 service_manager 中有关于 binder 的所有信息
    struct binder_state *bs;
...
    // 打开 binder驱动,得到文件操作符
    bs->fd = open("/dev/binder", O_RDWR);
...
     // service_manager自己设置的,大小为 128kb
    bs->mapsize = mapsize;
    //通过系统调用,mmap内存映射,mmap必须是 page的整数倍(即 4kb的整数倍)
    bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
...
}
  • 2.1.2 binder_become_context_manager 设为守护进程,成为 binder的管理者
frameworks/native/cmds/servicemanager/binder.c

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

由于file_operations结构体定义了文件操作符与Binder驱动的对应函数关联,所以iotrl对应执行Binder驱动binder_ioctl函数

2.1.2.1 binder_ioctl

kernel/drivers/staging/android/binder.c
// 3241
static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
// 3277 设置Context manager,即将自己设置为ServiceManager
case BINDER_SET_CONTEXT_MGR:
    ret = binder_ioctl_set_ctx_mgr(filp);

2.1.2.1.1 binder_ioctl_set_ctx_mgr

kernel/drivers/staging/android/binder.c

//3200
static int binder_ioctl_set_ctx_mgr(struct file *filp)
{
	int ret = 0;
	struct binder_proc *proc = filp->private_data;
	struct binder_context *context = proc->context;
	//获取当前进程的有效用户id
	kuid_t curr_euid = current_euid();
	//保证只创建一次 mgr_node对象,不为 null就直接返回
	if (context->binder_context_mgr_node) {
		pr_err("BINDER_SET_CONTEXT_MGR already set\n");
		ret = -EBUSY;
		goto out;
	}
	//检查当前进程是否有权限执行注册Context Manager的权限,在4.4版本的内核中该函数直接返回0.`kernel/include/linux/security.h`
	ret = security_binder_set_context_mgr(proc->tsk);
	if (ret < 0)
		goto out;
	//检查已有的uid是否有效
	if (uid_valid(context->binder_context_mgr_uid)) {
		//有效但是与当前运行线程的有效用户ID不相等,则出错。即线程只能注册自己,且只能有一个线程设置为Context Manager
		if (!uid_eq(context->binder_context_mgr_uid, curr_euid)) {
			pr_err("BINDER_SET_CONTEXT_MGR bad uid %d != %d\n",
			       from_kuid(&init_user_ns, curr_euid),
			       from_kuid(&init_user_ns,
					 context->binder_context_mgr_uid));
			ret = -EPERM;
			goto out;
		}
	} else {//之前设置的无效(如初始化状态,它的值是INVALID_UID),设置成当前进程的有效用户id。Service Manager启动第一次注册时走这个分支
		context->binder_context_mgr_uid = curr_euid;
	}
	//分配一个全新的binder_node,并赋值到全局变量binder_context_mgr_node中
	context->binder_context_mgr_node = binder_new_node(proc, 0, 0);
	if (!context->binder_context_mgr_node) {
		ret = -ENOMEM;
		goto out;
	}
	//更新相关引用计数
	context->binder_context_mgr_node->local_weak_refs++;
	context->binder_context_mgr_node->local_strong_refs++;
	context->binder_context_mgr_node->has_strong_ref = 1;
	context->binder_context_mgr_node->has_weak_ref = 1;
out:
	return ret;
}

2.1.2.1.1.1 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;
	}
	// 给新创建的binder_node 分配内核空间
	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;
	//初始化binder_node
	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);
	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;
}
  • 2.1.3 binder_loop 进入无限循环,处理client端发来的请求
frameworks/native/cmds/servicemanager/binder.c

//372
void binder_loop(struct binder_state *bs, binder_handler func)
{
    int res;
    struct binder_write_read bwr;
    uint32_t readbuf[32];

    // 初始化为 0
    bwr.write_size = 0;
    bwr.write_consumed = 0;
    bwr.write_buffer = 0;
    // 读写要处理的命令
    readbuf[0] = BC_ENTER_LOOPER;
    // 设置线程的 looper状态为循环状态
    binder_write(bs, readbuf, sizeof(uint32_t));

    for (;;) {
        //不为 0,进入 binder_thread_read
        bwr.read_size = sizeof(readbuf);
        bwr.read_consumed = 0;
        bwr.read_buffer = (uintptr_t) readbuf;
        //不断地 binder读数据,没有数据会进入休眠状态
        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);

        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_loop函数中会通过binder_write函数去设置线程的looper状态,然后在for循环中调用ioctl对应驱动的binder_ioctl函数,传入BINDER_WRITE_READ命令,执行到binder_ioctl_write_read函数,在此函数的读处理中执行binder_thread_read函数,一系列逻辑判断后,通过 ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));使刚启动的ServiceManager进入等待状态

binder_driver和ServiceManager交互的时序图:

  • 如何获取ServiceManager

获取Service Manager是通过defaultServiceManager()方法来完成

2.2 defaultServiceManager

frameworks/native/libs/binder/IServiceManager.cpp

//33
sp<IServiceManager> defaultServiceManager()
{
    //单例,如果不为空直接返回 
    if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
    
    {
        AutoMutex _l(gDefaultServiceManagerLock);
        // 创建或者获取 ServiceManager 时,ServiceManager 可能未准备就绪,这时通过 sleep 1秒后,循环尝试获取直到成功
        while (gDefaultServiceManager == NULL) {
            //创建 DefaultServiceManager
            gDefaultServiceManager = interface_cast<IServiceManager>(
                ProcessState::self()->getContextObject(NULL));
            if (gDefaultServiceManager == NULL)
                sleep(1);
        }
    }
    
    return gDefaultServiceManager;
}
  • 2.2.1 ProcessState::self()
frameworks/native/libs/binder/ProcessState.cpp

//70
sp<ProcessState> ProcessState::self()
{
    Mutex::Autolock _l(gProcessMutex);
        //单例
    if (gProcess != NULL) {
        return gProcess;
    }
    //实例化 ProcessState
    gProcess = new ProcessState;
    return gProcess;
}

2.2.1.1 ProcessState

frameworks/native/libs/binder/ProcessState.cpp

//339
ProcessState::ProcessState()
	//打开驱动
    : mDriverFD(open_driver())
...
        //  采用内存映射函数 mmap,给 binder分配一块大小为 (1M-8K)的虚拟地址空间,用来接收事务
        //  BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))
        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
...
}

2.2.1.1.1 open_driver()

frameworks/native/libs/binder/ProcessState.cpp

//311
static int open_driver()
{
    // 打开 /dev/binder设备,建立与内核的 Binder驱动的交互通道
    int fd = open("/dev/binder", O_RDWR);
...
          // 通过 ioctl设置 binder驱动,能支持的最大线程数  15个 
          // DEFAULT_MAX_BINDER_THREADS 15
        size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
        result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
...
    return fd;
}

ProcessState::self()主要做了三件事

1.打开binder驱动

2.设置最大线程15

3.mmap 设置共享内存大小 1M-8k

  • 2.2.2 ProcessState::getContextObject()
frameworks/native/libs/binder/ProcessState.cpp

//85
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
     // 参数为0,获取service_manager服务
    return getStrongProxyForHandle(0);
}

2.2.2.1 ProcessState::getStrongProxyForHandle

frameworks/native/libs/binder/ProcessState.cpp

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

    AutoMutex _l(mLock);
    // 查找 handle对应的资源项
    handle_entry* e = lookupHandleLocked(handle);

    if (e != NULL) {
        IBinder* b = e->binder;
        // 当handle值所对应的IBinder不存在或弱引用无效时
        if (b == NULL || !e->refs->attemptIncWeak(this)) {
            if (handle == 0) {
                Parcel data;
                // 通过ping操作测试binder是否准备就绪
                status_t status = IPCThreadState::self()->transact(
                        0, IBinder::PING_TRANSACTION, data, NULL, 0);
                if (status == DEAD_OBJECT)
                   return NULL;
            }
            // 创建BpBinder对象
            b = new BpBinder(handle); 
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }

    return result;
}

2.2.2.1.1 BpBinder

frameworks/native/libs/binder/BpBinder.cpp

//39
BpBinder::BpBinder(int32_t handle)
    : mHandle(handle)
    , mAlive(1)
    , mObitsSent(0)
    , mObituaries(NULL)
{
    ALOGV("Creating BpBinder %p handle %d\n", this, mHandle);
    // 支持强弱引用计数,OBJECT_LIFETIME_WEAK表示目标对象的生命周期受弱指针控制
    extendObjectLifetime(OBJECT_LIFETIME_WEAK);
    // handle所对应的 bindle弱引用 + 1
    IPCThreadState::self()->incWeakHandle(handle);
}

BpBinder是客户端用来与Server交互的代理类,p即Proxy的意思;BBinder则是proxy相对的一端,它是proxy交互的目的端。如果说Proxy代表客户端,那么BBinder则代表服务端。这里的BpBinderBBinder是一一对应的,即某个BpBinder只能和对应的BBinder交互。上面代码在defaultServiceManager()函数中创建了这个BpBinder,给BpBinder构造函数传的参数handle的值是0。这个0在整个Binder系统中有重要含义—因为0代表的就是ServiceManager所对应的BBinder

  • 2.2.3 interface_cast
frameworks/native/include/binder/IInterface.h

//41
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
    return INTERFACE::asInterface(obj);
}
//这是一个模板函数,等价于
inline sp<IServiceManager>interface_cast(const sp<IBinder>& obj)
{
    return IServiceManager::asInterface(obj);
}

2.2.3.1 IInterface.h

frameworks/native/include/binder/IInterface.h

//74
#define DECLARE_META_INTERFACE(INTERFACE)                               \
    static const android::String16 descriptor;                          \
    static android::sp<I##INTERFACE> asInterface(                       \
            const android::sp<android::IBinder>& obj);                  \
    virtual const android::String16& getInterfaceDescriptor() const;    \
    I##INTERFACE();                                                     \
    virtual ~I##INTERFACE();                                            \


#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \
    const android::String16 I##INTERFACE::descriptor(NAME);             \
    const android::String16&                                            \
            I##INTERFACE::getInterfaceDescriptor() const {              \
        return I##INTERFACE::descriptor;                                \
    }                                                                   \
    android::sp<I##INTERFACE> I##INTERFACE::asInterface(                \
            const android::sp<android::IBinder>& obj)                   \
    {                                                                   \
        android::sp<I##INTERFACE> intr;                                 \
        if (obj != NULL) {                                              \
            intr = static_cast<I##INTERFACE*>(                          \
                obj->queryLocalInterface(                               \
                        I##INTERFACE::descriptor).get());               \
            if (intr == NULL) {                                         \
                intr = new Bp##INTERFACE(obj);                          \
            }                                                           \
        }                                                               \
        return intr;                                                    \
    }                                                                   \
    I##INTERFACE::I##INTERFACE() { }                                    \
    I##INTERFACE::~I##INTERFACE() { }                                   \

这里面中有两个关键的宏定义

2.2.3.2 IServiceManager::asInterface

frameworks/native/include/binder/IServiceManager.h

//33
class IServiceManager : public IInterface
{
public:
    DECLARE_META_INTERFACE(ServiceManager);
    virtual sp<IBinder>         getService( const String16& name) const = 0;
    virtual sp<IBinder>         checkService( const String16& name) const = 0;
    virtual status_t            addService( const String16& name,
                                            const sp<IBinder>& service,
                                            bool allowIsolated = false) = 0;

    virtual Vector<String16>    listServices() = 0;

    enum {
        GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
        CHECK_SERVICE_TRANSACTION,
        ADD_SERVICE_TRANSACTION,
        LIST_SERVICES_TRANSACTION,
    };
};

通过IInterface.h中的宏定义展开可获得

static const android::String16 descriptor;
static android::sp< IServiceManager > asInterface(const 
android::sp<android::IBinder>& obj)
virtual const android::String16& getInterfaceDescriptor() const;
IServiceManager ();
virtual ~IServiceManager();

该过程主要是声明asInterface(),getInterfaceDescriptor()方法。

frameworks/native/libs/binder/IServiceManager.cpp

//185
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");

通过IInterface.h中的宏定义展开可获得

const android::String16 
IServiceManager::descriptor(“android.os.IServiceManager”);
const android::String16& IServiceManager::getInterfaceDescriptor() const
{
     return IServiceManager::descriptor;
}
 android::sp<IServiceManager> IServiceManager::asInterface(const 
android::sp<android::IBinder>& obj)
{
       android::sp<IServiceManager> intr;
        if(obj != NULL) {
           intr = static_cast<IServiceManager *>(
               obj->queryLocalInterface(IServiceManager::descriptor).get());
           if (intr == NULL) {
                // 等价于 new BpServiceManager(BpBinder)
                intr = new BpServiceManager(obj);
            }
        }
       return intr;
}
IServiceManager::IServiceManager () { }
IServiceManager::~ IServiceManager() { }

2.2.4 BpServiceManager

frameworks/native/libs/binder/IServiceManager.cpp

//126
class BpServiceManager : public BpInterface<IServiceManager>
{
public:
    BpServiceManager(const sp<IBinder>& impl)
        : BpInterface<IServiceManager>(impl)
    {
    }
...

};

2.2.4.1 BpInterface::BpInterface

frameworks/native/include/binder/IInterface.h

//134
template<typename INTERFACE>
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
    : BpRefBase(remote)

2.2.4.1.1 BpRefBase

frameworks/native/libs/binder/Binder.cpp

// 241 mRemote指向 new BpBinder(0),从而 BpServiceManager能够利用 Binder进行通过通信
BpRefBase::BpRefBase(const sp<IBinder>& o)
    : mRemote(o.get()), mRefs(NULL), mState(0)

那么,获取ServiceManager的时序图应该是这样的