本文参考《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);
r