本文参考《Android系统源代码情景分析》,作者罗升阳
一、service manager代码:
~/Android/frameworks/base/cmd/servicemanager
----binder.c
----service_manager.c
----binder.h
驱动层代码:
~/Android//kernel/goldfish/drivers/staging/android
----binder.c
----binder.h
二、源码分析
在上一篇文章中,Android Binder进程间通信---FregServer进程,发送BC_TRANSACTION,睡眠等待
http://blog.csdn.net/jltxgcy/article/details/26076149,
list_add_tail(&t->work.entry, target_list);已经加入到目标进程的todo列表。
wake_up_interruptible(target_wait);唤醒了目标进程。
还记得在Andorid Binder进程间通信---Service Manager进程启动,睡眠等待一文中
http://blog.csdn.net/jltxgcy/article/details/25797011,最后进程睡眠等待直到有新的未处理项为止,此时有新的处理项,继续执行binder_thread_read函数。实现如下:
~/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;
.........
while (1) {
uint32_t cmd;
struct binder_transaction_data tr;
struct binder_work *w;
struct binder_transaction *t = NULL;
if (!list_empty(&thread->todo))
w = list_first_entry(&thread->todo, struct binder_work, entry);
else if (!list_empty(&proc->todo) && wait_for_proc_work)
w = list_first_entry(&proc->todo, struct binder_work, entry);//将要处理的工作项保存在binder_work结构体w中
else {
if (ptr - buffer == 4 && !(thread->looper & BINDER_LOOPER_STATE_NEED_RETURN)) /* no data added */
goto retry;
break;
}
........
switch (w->type) {
case BINDER_WORK_TRANSACTION: {
t = container_of(w, struct binder_transaction, work);//由于binder_work结构体w的类型为BINDER_WORK_TRANSACTION,即它是一个嵌入在一个binder_transaction结构体中的工作项,因此可以安全地将它转换为一个binder_transaction结构体t
} break;
.........
}
if (!t)
continue;
BUG_ON(t->buffer == NULL);
if (t->buffer->target_node) {
struct binder_node *target_node = t->buffer->target_node;
tr.target.ptr = target_node->ptr;//Binder实体对象ptr为NULL
tr.cookie = target_node->cookie;//Binder实体对象cookie为NULL
t->saved_priority = task_nice(current);
if (t->priority < target_node->min_priority &&
!(t->flags & TF_ONE_WAY))
binder_set_nice(t->priority);
else if (!(t->flags & TF_ONE_WAY) ||
t->saved_priority > target_node->min_priority)
binder_set_nice(target_node->min_priority);
cmd = BR_TRANSACTION;//cmd设置BR_TRANSACTION
} else {
.....
}
tr.code = t->code;//ADD_SERVICE_TRANCATION
tr.flags = t->flags;//TF_ACCEPTS_FDS
tr.sender_euid = t->sender_euid;
if (t->from) {
struct task_struct *sender = t->from->proc->tsk;
tr.sender_pid = task_tgid_nr_ns(sender, current->nsproxy->pid_ns);
} else {
.......
}
tr.data_size = t->bu