本文参考《Android系统源代码情景分析》,作者罗升阳。
一、~/Android/frameworks/base/cmd/servicemanager
-----binder.h
-----binder.c
-----service_manager.c
~/Android//kernel/goldfish/drivers/staging/android
-----binder.c
-----binder.h
二、源码分析
1、从service_manager.c的main开始执行。
----~/Android/frameworks/base/cmd/servicemanager/service_manager.c
int main(int argc, char **argv) { struct binder_state *bs; void *svcmgr = BINDER_SERVICE_MANAGER; bs = binder_open(128*1024); if (binder_become_context_manager(bs)) { LOGE("cannot become context manager (%s)\n", strerror(errno)); return -1; } svcmgr_handle = svcmgr;//注意svcmgr_handle与下面的svcmgr_handler不一样,svcmgr_handle为全局变量,目前为空的函数指针,((void*)0) binder_loop(bs, svcmgr_handler);//svcmgr_handler是一个函数指针,指向具体的函数 return 0; }---- ~/Android/frameworks/base/cmd/servicemanager/binder.c
struct binder_state { int fd; void *mapped; unsigned mapsize; };---- ~/Android/frameworks/base/cmd/servicemanager/binder.h
#define BINDER_SERVICE_MANAGER ((void*) 0)
Service Manager是一个特殊的Service组件,它的特殊之处就在于与Service Manager进程的Binder本地对象是一个虚拟的对象。这个虚拟的Binder本地对象的地址值等于0,并且在Binder驱动程序中引用了它的Binder引用对象的句柄值也等于0。
ServiceManager的启动过程由三个步骤组成:第一是调用函数binder_open打开设备文件/dev/binder,以及将它映射到本进程地址空间;第二是调用binder_become_context_manager将自己注册为Binder进程间通信机制的上下文管理者;第三步是调用函数binder_loop来循环等待和处理Client进程的通信要求。
2、打开和映射Binder设备文件
----~/Android/frameworks/base/cmd/servicemanager/binder.c
struct binder_state *binder_open(unsigned mapsize) { struct binder_state *bs; bs = malloc(sizeof(*bs)); if (!bs) { errno = ENOMEM; return 0; } bs->fd = open("/dev/binder", O_RDWR);//文件描述符保存在fd中 if (bs->fd < 0) { fprintf(stderr,"binder: cannot open device (%s)\n", strerror(errno)); goto fail_open; } bs->mapsize = mapsize;//128*1024 bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);//映射到本进程地址空间 if (bs->mapped == MAP_FAILED) { fprintf(stderr,"binder: cannot map device (%s)\n", strerror(errno)); goto fail_map; } /* TODO: check version */ return bs; fail_map: close(bs->fd); fail_open: free(bs); return 0; }其中open("/dev/binder", O_RDWR)映射到binder驱动程序binder_open方法。
binder_open方法位于~/Android/kernel/goldfish/drivers/staging/android/binder.c
static int binder_open(struct inode *nodp, struct file *filp) { struct binder_proc *proc; if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE) printk(KERN_INFO "binder_open: %d:%d\n", current->group_leader->pid, current->pid); proc = kzalloc(sizeof(*proc), GFP_KERNEL);//创建binder_proc结构体 if (proc == NULL) return -ENOMEM; get_task_struct(current); proc->tsk = current; //初始化各个参数 INIT_LIST_HEAD(&proc->todo); init_waitqueue_head(&proc->wait); proc->default_priority = task_nice(current); mutex_lock(&binder_lock); binder_stats.obj_created[BINDER_STAT_PROC]++; hlist_add_head(&proc->proc_node, &binder_procs);//将binder_proc结构体proc加入到一个全局hash队列binder_procs中 proc->pid = current->group_leader->pid;//进程的pid INIT_LIST_HEAD(&proc->delivered_death); filp->private_data = proc;//将binder_proc结构体proc保存在参数filp的成员变量private_data中 mutex_unlock(&binder_lock); if (binder_proc_dir_entry_proc) {//如果存在/proc/binder/proc目录 char strbuf[11]; snprintf(strbuf, sizeof(strbuf), "%u", proc->pid); remove_proc_entry(strbuf, binder_proc_dir_entry_proc); create_proc_read_entry(strbuf, S_IRUGO, binder_proc_dir_entry_proc, binder_read_proc_proc, proc);//在/proc/binder/proc目录下创建一个以进程ID为名称的只读文件 } return 0; }创建了binder_proc结构体,分别初始化各个参数,将binder_proc结构体proc加入到一个全局hash队列binder_procs中。Binder驱动程序将所有打开了设备文件/dev/binder的进程都加入全局hash队列binder_procs中,因此,通过遍历这个hash队列就知道系统当前有多少进程在使用Binder进程间通信机制。然后将binder_proc结构体proc保存在参数filp的成员变量private_data中。最后在/proc/binder/proc目录下创建一个以进程ID为名称的只读文件,并且以函数binder_read_proc_proc作为它的文件内容读取函数。通过读取文件/proc/binder/proc/<PID>的内容,我们就可以获得进程<PID>的Binder线程池,Binder实体对象,Binder引用对象,以及内核缓冲区等信息。
其中mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0)映射到binder驱动程序binder_mmap方法,暂时先不分析。
3、注册为Binder上下文管理者
---~/Android/frameworks/base/cmd/servicemanager/binder.c
int binder_become_context_manager(struct binder_state *bs) { return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0); }ioctl方法映射到binder驱动程序binder_ioctl方法。
binder_ioctl位于~/Android/kernel/goldfish/drivers/staging/android/binder.c
static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { int ret; struct binder_proc *proc = filp->private_data;//获取刚刚在open中创建的binder_proc结构体 struct binder_thread *thread; unsigned int size = _IOC_SIZE(cmd);//命令的大小 void __user *ubuf = (void __user *)arg;//参数地址 ......... mutex_lock(&binder_lock); thread = binder_get_thread(proc);//获取或者创建一个binder_thread结构体 if (thread == NULL) { ret = -ENOMEM; goto err; } switch (cmd) { ............ case BINDER_SET_CONTEXT_MGR: if (binder_context_mgr_node != NULL) { ......... } if (binder_context_mgr_uid != -1) { ......... } else binder_context_mgr_uid = current->cred->euid;//初始化进程有效用户ID binder_context_mgr_node = binder_new_node(proc, NULL, NULL);//初始化一个Binder实体对象 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; ............. } ret = 0; err: if (thread) thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN; mutex_unlock(&binder_lock); ............. return ret; }binder_get_thread实现如下:
~/Android/kernel/goldfish/drivers/staging/android/binder.c
static struct binder_thread *binder_get_thread(struct binder_proc *proc) { struct binder_thread *thread = NULL; struct rb_node *parent = NULL; struct rb_node **p = &proc->threads.rb_node; while (*p) {//根据当前主线程pid,来查找是否已经分配了binder_thread结构体 parent = *p; thread = rb_entry(parent, struct binder_thread, rb_node); if (current->pid < thread->pid) p = &(*p)->rb_left; else if (current->pid > thread->pid) p = &(*p)->rb_right; else break; } if (*p == NULL) {//如果没有找到 thread = kzalloc(sizeof(*thread), GFP_KERNEL);//分配binder_thread结构体 if (thread == NULL) return NULL; binder_stats.obj_created[BINDER_STAT_THREAD]++; thread->proc = proc;//初始化各个变量 thread->pid = current->pid;//线程的pid init_waitqueue_head(&thread->wait); INIT_LIST_HEAD(&thread->todo); rb_link_node(&thread->rb_node, parent, p);//根据pid将thread->rb_node插入到proc->threads维护的红黑树中 rb_insert_color(&thread->rb_node, &proc->threads); thread->looper |= BINDER_LOOPER_STATE_NEED_RETURN; thread->return_error = BR_OK; thread->return_error2 = BR_OK; } return thread; }一个进程会有很多线程,所以thread->rb_node为proc->threads维护的红黑数中的一个节点。thread按照pid大小将rb_node插入到proc->threads维护的红黑树的对应节点处。所以首先根据当前主线程pid,来查找是否已经分配了binder_thread结构体。如果没有那么分配binder_thread结构体,初始化各个变量,根据pid将thread->rb_node插入到proc->threads维护的红黑树中。将looper状态设备为BINDER_LOOPER_STATE_NEED_RETURN,表示该线程在完成当前操作之后,需要马上返回到用户空间,而不可以去处理进程间的通信请求。
全局变量binder_context_mgr_node用来描述一个Binder实体对象,如果它的值不为NULL,说明已经注册了Binder进程间通信上下文管理者了。全局变量binder_context_mgr_uid用来描述进程有效用户ID,如果它的值不等于-1,说明已经注册了Binder进程间通信上下文管理者了。目前没有Binder进程间通信上下文管理者,所以binder_context_mgr_uid和binder_context_mgr_node都要初始化。
binder_context_mgr_node实现如下:
-----~/Android/kernel/goldfish/drivers/staging/android/binder.c
static struct binder_node * binder_new_node(struct binder_proc *proc, void __user *ptr, void __user *cookie) { struct rb_node **p = &proc->nodes.rb_node; struct rb_node *parent = NULL; struct binder_node *node; while (*p) {//根据node的ptr,来查找是否已经分配了binder_node结构体 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(sizeof(*node), GFP_KERNEL);//如果没有找到,分配binder_node结构体 if (node == NULL) return NULL; binder_stats.obj_created[BINDER_STAT_NODE]++; rb_link_node(&node->rb_node, parent, p);//根据ptr将node->rb_node插入proc->nodes中 rb_insert_color(&node->rb_node, &proc->nodes); node->debug_id = ++binder_last_id;//初始化各个变量 node->proc = proc; node->ptr = ptr;//NULL node->cookie = cookie;//NULL node->work.type = BINDER_WORK_NODE; INIT_LIST_HEAD(&node->work.entry); INIT_LIST_HEAD(&node->async_todo); if (binder_debug_mask & BINDER_DEBUG_INTERNAL_REFS) printk(KERN_INFO "binder: %d:%d node %d u%p c%p created\n", proc->pid, current->pid, node->debug_id, node->ptr, node->cookie); return node; }
一个进程会有很多实体对象,所以node->rb_node为proc->nodes维护的红黑数中的一个节点。node按照ptr地址大小将rb_node插入到proc->threads维护的红黑树的对应节点处。所以首先根据当前node的ptr,来查找是否已经分配了binder_node结构体。如果没有那么分配binder_node结构体,初始化各个变量,根据ptr将thread->rb_node插入到proc->threads维护的红黑树中。
然后返回binder_ioctl中, 刚才Service Manager进程的Binder实体对象binder_context_mgr_node内部弱引用计数local_weak_refs以及内部强引用计数local_strong_refs进行初始化,即将它们的值设置为1,避免Binder驱动程序将其释放。接着又将成员变量has_strong_ref和has_weak_ref的值设置为1,表示Binder驱动程序已经请求Service Manager进程本地对象强引用计数和弱引用计数。由于Service Manager进程本地对象在运行过程中一直存在,所以实际上不需要请求增加它的引用计数,而是直接将它对应的Binder实体对象binder_context_mgr_node的成员变量has_strong_ref和has_weak_ref的值设置为1。
4、循环等待Client进程请求
返回用户空间,main函数开始执行binder_loop,实现如下:
---~/Android/frameworks/base/cmd/servicemanager/binder.c
void binder_loop(struct binder_state *bs, binder_handler func) { int res; struct binder_write_read bwr; unsigned readbuf[32]; bwr.write_size = 0; bwr.write_consumed = 0; bwr.write_buffer = 0; readbuf[0] = BC_ENTER_LOOPER;//首先将BC_ENTER_LOOPER协议写入缓冲区readbuf中 binder_write(bs, readbuf, sizeof(unsigned));//调用binder_write将它发送到Binder驱动程序中 for (;;) { bwr.read_size = sizeof(readbuf); bwr.read_consumed = 0; bwr.read_buffer = (unsigned) readbuf; res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);//bwr.write_size为0,bwr.read_size不为0 if (res < 0) { LOGE("binder_loop: ioctl failed (%s)\n", strerror(errno)); break; } res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func); if (res == 0) { LOGE("binder_loop: unexpected reply?!\n"); break; } if (res < 0) { LOGE("binder_loop: io error %d %s\n", res, strerror(errno)); break; } } }首先将BC_ENTER_LOOPER协议写入缓冲区readbuf中,接着调用binder_write将它发送到Binder驱动程序中。函数binder_write的实现如下:
---~/Android/frameworks/base/cmd/servicemanager/binder.c
int binder_write(struct binder_state *bs, void *data, unsigned len) { struct binder_write_read bwr; int res; bwr.write_size = len; bwr.write_consumed = 0; bwr.write_buffer = (unsigned) data; bwr.read_size = 0; bwr.read_consumed = 0; bwr.read_buffer = 0; res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);//bwr的write_size不为0,read_size为0 if (res < 0) { fprintf(stderr,"binder_write: ioctl failed (%s)\n", strerror(errno)); } return res; }ioctl方法同样映射到binder驱动程序 binder_ioctl方法。
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; ......... mutex_lock(&binder_lock); thread = binder_get_thread(proc);//上次获取的thread,looper为0 if (thread == NULL) { ret = -ENOMEM; goto err; } switch (cmd) {//cmd为上面传递过来的BINDER_WRITE_READ case BINDER_WRITE_READ: { struct binder_write_read bwr; if (size != sizeof(struct binder_write_read)) { ret = -EINVAL; goto err; } if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {//从用户空间传进来的一个binder_write_read结构体拷贝出来,并且保存在变量bwr中 ret = -EFAULT; goto err; } ......... if (bwr.write_size > 0) {//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) {//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))) {//将结果返回用户空间bwr ret = -EFAULT; goto err; } break; } .......... ret = 0; err: if (thread) thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN;//looper为BINDER_LOOPER_STATE_ENTERED,由于对应位已经为0,此时执行此句无效果 mutex_unlock(&binder_lock); ........... return ret; }由于bwr.write_size大于0,开始执行binder_thread_write,实现如下:
binder_ioctl位于~/Android/kernel/goldfish/drivers/staging/android/binder.c
int binder_thread_write(struct binder_proc *proc, struct binder_thread *thread, void __user *buffer, int size, signed long *consumed) { uint32_t cmd; void __user *ptr = buffer + *consumed;//起始位置 void __user *end = buffer + size;//结束位置 while (ptr < end && thread->return_error == BR_OK) { if (get_user(cmd, (uint32_t __user *)ptr))//cmd为BC_ENTER_LOOPER return -EFAULT; ptr += sizeof(uint32_t);//由于只有一个cmd,此时ptr已经等于end ............ switch (cmd) { ........... case BC_ENTER_LOOPER: .............. if (thread->looper & BINDER_LOOPER_STATE_REGISTERED) {//此时looper为0,不会执行这里 thread->looper |= BINDER_LOOPER_STATE_INVALID; binder_user_error("binder: %d:%d ERROR:" " BC_ENTER_LOOPER called after " "BC_REGISTER_LOOPER\n", proc->pid, thread->pid); } thread->looper |= BINDER_LOOPER_STATE_ENTERED;//执行本次写操作,最终的目的居然是looper设置成BINDER_LOOPER_STATE_ENTERED break; ......... *consumed = ptr - buffer;//由于只有一个cmd,consumed为size } return 0; }返回binder_ioctl,bwr.read_size等于0,不会执行,最后将结果返回用户空间bwr。
返回用户空间,接着执行binder_loop,从上面我们看出来,驱动程序是否执行读、写操作,取决于用户空间write_size,read_size的大小。此时write_size为0,read_size不为0, ioctl方法同样映射到binder驱动程序binder_ioctl方法。
binder_ioctl位于~/Android/kernel/goldfish/drivers/staging/android/binder.c
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; ......... mutex_lock(&binder_lock); thread = binder_get_thread(proc);//上次获取的thread,looper为BINDER_LOOPER_STATE_ENTERED if (thread == NULL) { ret = -ENOMEM; goto err; } switch (cmd) {//cmd为上面传递过来的BINDER_WRITE_READ case BINDER_WRITE_READ: { struct binder_write_read bwr; if (size != sizeof(struct binder_write_read)) { ret = -EINVAL; goto err; } if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {//从用户空间传进来的一个binder_write_read结构体拷贝出来,并且保存在变量bwr中 ret = -EFAULT; goto err; } ......... if (bwr.write_size > 0) {//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) {//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))) {//将结果返回用户空间bwr ret = -EFAULT; goto err; } break; } .......... ret = 0; err: if (thread) thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN; mutex_unlock(&binder_lock); ........... return ret; }
由于bwr.read_size大于0,开始执行binder_thread_read,实现如下:
binder_ioctl位于~/Android/kernel/goldfish/drivers/staging/android/binder.c
static int binder_thread_read(struct binder_proc *proc, struct binder_thread *thread, void __user *buffer, int size, signed long *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) { if (put_user(BR_NOOP, (uint32_t __user *)ptr))//BR_NOOP存入刚才的局部变量中 return -EFAULT; ptr += sizeof(uint32_t); } retry: wait_for_proc_work = thread->transaction_stack == NULL && list_empty(&thread->todo);//wait_for_proc_work目前为1,表示线程没有要处理的任务 if (thread->return_error != BR_OK && ptr < end) { .......... } thread->looper |= BINDER_LOOPER_STATE_WAITING;//looper为BINDER_LOOPER_STATE_ENTERED,BINDER_LOOPER_STATE_WAITING if (wait_for_proc_work)//为1 proc->ready_threads++;//ready_threads为1,进程多了一个空闲线程 mutex_unlock(&binder_lock); if (wait_for_proc_work) {//为1 if (!(thread->looper & (BINDER_LOOPER_STATE_REGISTERED | BINDER_LOOPER_STATE_ENTERED))) { // 此时为false,必须是两个状态之一 ............... } binder_set_nice(proc->default_priority);//把当前线程的优先级设置为它所属进程的优先级 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 { if (non_block) {//非阻塞要立刻返回处理结果 if (!binder_has_thread_work(thread))有任务就接下往下执行,没有任务就返回 ret = -EAGAIN; } else ret = wait_event_interruptible(thread->wait, binder_has_thread_work(thread));//睡眠等待直到线程有新的未处理项为止 } mutex_lock(&binder_lock); if (wait_for_proc_work)//为1 proc->ready_threads--;//ready_thread为0 thread->looper &= ~BINDER_LOOPER_STATE_WAITING;//looper为BINDER_LOOPER_STATE_ENTERED if (ret) return ret; while (1) { ........ } done: *consumed = ptr - buffer; .......... return 0; }
static int binder_has_proc_work(struct binder_proc *proc, struct binder_thread *thread) { return !list_empty(&proc->todo) || (thread->looper & BINDER_LOOPER_STATE_NEED_RETURN); } static int binder_has_thread_work(struct binder_thread *thread) { return !list_empty(&thread->todo) || thread->return_error != BR_OK || (thread->looper & BINDER_LOOPER_STATE_NEED_RETURN); }如果线程thread中没有要处理的数据,那么就处理进程proc上等待的数据。如果进程上没有数据要处理,那么睡眠等待直到其所属的进程有新的未处理项为止。
如果线程thread中有要处理的数据,那么就处理线程thread上的数据。如果线程上没有数据要处理,那么睡眠等待直到线程有新的未处理项为止。
如果是非阻塞访问,如果没有数据,就立刻返回,不会睡眠等待。如果有数据,就继续往下执行。
目前由于线程thread没有要处理的数据,进程上也没有要处理的数据,那么睡眠等待直到其所属的进程有新的未处理项为止。
三、目前为止各对象的引用计数
Service Manager本地对象,不需要引用计数,因为永远不会销毁。
Service Manager实体对象,内部强引用计数为1,内部弱引用计数为1,has_strong_refs为1,has_week_refs为1。