本文参考《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/其中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。