Welcome 微信登录

首页 / 操作系统 / Linux / 浅谈Service Manager成为Android进程间通信(IPC)机制Binder守护进程之路

上一篇文章Android进程间通信(IPC)机制Binder简要介绍和学习计划简要介绍了Android系统进程间通信机制Binder的总体架构,它由Client、Server、Service Manager和驱动程序Binder四个组件构成。本文着重介绍组件Service Manager,它是整个Binder机制的守护进程,用来管理开发者创建的各种Server,并且向Client提供查询Server远程接口的功能。 相关阅读:Android进程间通信(IPC)机制Binder简要介绍和学习计划  http://www.linuxidc.com/Linux/2011-07/39269.htm        既然Service Manager组件是用来管理Server并且向Client提供查询Server远程接口的功能,那么,Service Manager就必然要和Server以及Client进行通信了。我们知道,Service Manger、Client和Server三者分别是运行在独立的进程当中,这样它们之间的通信也属于进程间通信了,而且也是采用Binder机制进行进程间通信,因此,Service Manager在充当Binder机制的守护进程的角色的同时,也在充当Server的角色,然而,它是一种特殊的Server,下面我们将会看到它的特殊之处。       与Service Manager相关的源代码较多,这里不会完整去分析每一行代码,主要是带着Service Manager是如何成为整个Binder机制中的守护进程这条主线来一步一步地深入分析相关源代码,包括从用户空间到内核空间的相关源代码。希望读者在阅读下面的内容之前,先阅读一下前一篇文章提到的两个参考资料Android深入浅出之Binder机制Android Binder设计与实现,熟悉相关概念和数据结构,这有助于理解下面要分析的源代码。       Service Manager在用户空间的源代码位于frameworks/base/cmds/servicemanager目录下,主要是由binder.h、binder.c和service_manager.c三个文件组成。Service Manager的入口位于service_manager.c文件中的main函数:
  1. int main(int argc, char **argv)  
  2. {  
  3.     struct binder_state *bs;  
  4.     void *svcmgr = BINDER_SERVICE_MANAGER;  
  5.   
  6.     bs = binder_open(128*1024);  
  7.   
  8.     if (binder_become_context_manager(bs)) {  
  9.         LOGE("cannot become context manager (%s) ", strerror(errno));  
  10.         return -1;  
  11.     }  
  12.   
  13.     svcmgr_handle = svcmgr;  
  14.     binder_loop(bs, svcmgr_handler);  
  15.     return 0;  
  16. }  
        main函数主要有三个功能:一是打开Binder设备文件;二是告诉Binder驱动程序自己是Binder上下文管理者,即我们前面所说的守护进程;三是进入一个无穷循环,充当Server的角色,等待Client的请求。进入这三个功能之间,先来看一下这里用到的结构体binder_state、宏BINDER_SERVICE_MANAGER的定义:         struct binder_state定义在frameworks/base/cmds/servicemanager/binder.c文件中:
  1. struct binder_state  
  2. {  
  3.     int fd;  
  4.     void *mapped;  
  5.     unsigned mapsize;  
  6. };  
        fd是文件描述符,即表示打开的/dev/binder设备文件描述符;mapped是把设备文件/dev/binder映射到进程空间的起始地址;mapsize是上述内存映射空间的大小。         宏BINDER_SERVICE_MANAGER定义frameworks/base/cmds/servicemanager/binder.h文件中: 
  1. /* the one magic object */  
  2. #define BINDER_SERVICE_MANAGER ((void*) 0)  
        它表示Service Manager的句柄为0。Binder通信机制使用句柄来代表远程接口,这个句柄的意义和Windows编程中用到的句柄是差不多的概念。前面说到,Service Manager在充当守护进程的同时,它充当Server的角色,当它作为远程接口使用时,它的句柄值便为0,这就是它的特殊之处,其余的Server的远程接口句柄值都是一个大于0 而且由Binder驱动程序自动进行分配的。         函数首先是执行打开Binder设备文件的操作binder_open,这个函数位于frameworks/base/cmds/servicemanager/binder.c文件中: 
  1. struct binder_state *binder_open(unsigned mapsize)  
  2. {  
  3.     struct binder_state *bs;  
  4.   
  5.     bs = malloc(sizeof(*bs));  
  6.     if (!bs) {  
  7.         errno = ENOMEM;  
  8.         return 0;  
  9.     }  
  10.   
  11.     bs->fd = open("/dev/binder", O_RDWR);  
  12.     if (bs->fd < 0) {  
  13.         fprintf(stderr,"binder: cannot open device (%s) ",  
  14.                 strerror(errno));  
  15.         goto fail_open;  
  16.     }  
  17.   
  18.     bs->mapsize = mapsize;  
  19.     bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);  
  20.     if (bs->mapped == MAP_FAILED) {  
  21.         fprintf(stderr,"binder: cannot map device (%s) ",  
  22.                 strerror(errno));  
  23.         goto fail_map;  
  24.     }  
  25.   
  26.         /* TODO: check version */  
  27.   
  28.     return bs;  
  29.   
  30. fail_map:  
  31.     close(bs->fd);  
  32. fail_open:  
  33.     free(bs);  
  34.     return 0;  
  35. }  
       通过文件操作函数open来打开/dev/binder设备文件。设备文件/dev/binder是在Binder驱动程序模块初始化的时候创建的,我们先看一下这个设备文件的创建过程。进入到kernel/common/drivers/staging/android目录中,打开binder.c文件,可以看到模块初始化入口binder_init:  
  1. static struct file_operations binder_fops = {  
  2.     .owner = THIS_MODULE,  
  3.     .poll = binder_poll,  
  4.     .unlocked_ioctl = binder_ioctl,  
  5.     .mmap = binder_mmap,  
  6.     .open = binder_open,  
  7.     .flush = binder_flush,  
  8.     .release = binder_release,  
  9. };  
  10.   
  11. static struct miscdevice binder_miscdev = {  
  12.     .minor = MISC_DYNAMIC_MINOR,  
  13.     .name = "binder",  
  14.     .fops = &binder_fops  
  15. };  
  16.   
  17. static int __init binder_init(void)  
  18. {  
  19.     int ret;  
  20.   
  21.     binder_proc_dir_entry_root = proc_mkdir("binder", NULL);  
  22.     if (binder_proc_dir_entry_root)  
  23.         binder_proc_dir_entry_proc = proc_mkdir("proc", binder_proc_dir_entry_root);  
  24.     ret = misc_register(&binder_miscdev);  
  25.     if (binder_proc_dir_entry_root) {  
  26.         create_proc_read_entry("state", S_IRUGO, binder_proc_dir_entry_root, binder_read_proc_state, NULL);  
  27.         create_proc_read_entry("stats", S_IRUGO, binder_proc_dir_entry_root, binder_read_proc_stats, NULL);  
  28.         create_proc_read_entry("transactions", S_IRUGO, binder_proc_dir_entry_root, binder_read_proc_transactions, NULL);  
  29.         create_proc_read_entry("transaction_log", S_IRUGO, binder_proc_dir_entry_root, binder_read_proc_transaction_log, &binder_transaction_log);  
  30.         create_proc_read_entry("failed_transaction_log", S_IRUGO, binder_proc_dir_entry_root, binder_read_proc_transaction_log, &binder_transaction_log_failed);  
  31.     }  
  32.     return ret;  
  33. }  
  34.   
  35. device_initcall(binder_init);  
        创建设备文件的地方在misc_register函数里面,关于misc设备的注册,我们在Android日志系统驱动程序Logger源代码分析一文中有提到,有兴趣的读取不访去了解一下。其余的逻辑主要是在/proc目录创建各种Binder相关的文件,供用户访问。从设备文件的操作方法binder_fops可以看出,前面的binder_open函数执行语句:
  1. bs->fd = open("/dev/binder", O_RDWR);  
        就进入到Binder驱动程序的binder_open函数了: 
  1. static int binder_open(struct inode *nodp, struct file *filp)  
  2. {  
  3.     struct binder_proc *proc;  
  4.   
  5.     if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE)  
  6.         printk(KERN_INFO "binder_open: %d:%d ", current->group_leader->pid, current->pid);  
  7.   
  8.     proc = kzalloc(sizeof(*proc), GFP_KERNEL);  
  9.     if (proc == NULL)  
  10.         return -ENOMEM;  
  11.     get_task_struct(current);  
  12.     proc->tsk = current;  
  13.     INIT_LIST_HEAD(&proc->todo);  
  14.     init_waitqueue_head(&proc->wait);  
  15.     proc->default_priority = task_nice(current);  
  16.     mutex_lock(&binder_lock);  
  17.     binder_stats.obj_created[BINDER_STAT_PROC]++;  
  18.     hlist_add_head(&proc->proc_node, &binder_procs);  
  19.     proc->pid = current->group_leader->pid;  
  20.     INIT_LIST_HEAD(&proc->delivered_death);  
  21.     filp->private_data = proc;  
  22.     mutex_unlock(&binder_lock);  
  23.   
  24.     if (binder_proc_dir_entry_proc) {  
  25.         char strbuf[11];  
  26.         snprintf(strbuf, sizeof(strbuf), "%u", proc->pid);  
  27.         remove_proc_entry(strbuf, binder_proc_dir_entry_proc);  
  28.         create_proc_read_entry(strbuf, S_IRUGO, binder_proc_dir_entry_proc, binder_read_proc_proc, proc);  
  29.     }  
  30.   
  31.     return 0;  
  32. }  
         这个函数的主要作用是创建一个struct binder_proc数据结构来保存打开设备文件/dev/binder的进程的上下文信息,并且将这个进程上下文信息保存在打开文件结构struct file的私有数据成员变量private_data中,这样,在执行其它文件操作时,就通过打开文件结构struct file来取回这个进程上下文信息了。这个进程上下文信息同时还会保存在一个全局哈希表binder_procs中,驱动程序内部使用。binder_procs定义在文件的开头:
 
  1. static HLIST_HEAD(binder_procs);  
        结构体struct binder_proc也是定义在kernel/common/drivers/staging/android/binder.c文件中:
 
  1. struct binder_proc {  
  2.     struct hlist_node proc_node;  
  3.     struct rb_root threads;  
  4.     struct rb_root nodes;  
  5.     struct rb_root refs_by_desc;  
  6.     struct rb_root refs_by_node;  
  7.     int pid;  
  8.     struct vm_area_struct *vma;  
  9.     struct task_struct *tsk;  
  10.     struct files_struct *files;  
  11.     struct hlist_node deferred_work_node;  
  12.     int deferred_work;  
  13.     void *buffer;  
  14.     ptrdiff_t user_buffer_offset;  
  15.   
  16.     struct list_head buffers;  
  17.     struct rb_root free_buffers;  
  18.     struct rb_root allocated_buffers;  
  19.     size_t free_async_space;  
  20.   
  21.     struct page **pages;  
  22.     size_t buffer_size;  
  23.     uint32_t buffer_free;  
  24.     struct list_head todo;  
  25.     wait_queue_head_t wait;  
  26.     struct binder_stats stats;  
  27.     struct list_head delivered_death;  
  28.     int max_threads;  
  29.     int requested_threads;  
  30.     int requested_threads_started;  
  31.     int ready_threads;  
  32.     long default_priority;  
  33. };