本文基于Android_9.0、kernel_3.18源码
通过Binder(三)到Binder(六)的相关文章,我们详细介绍了Binder服务启动、服务注册的流程;其中服务注册相当于servicemanager提供的一个方法,AMS在system_server进程中,AMS完成注册即通过binder完成了一次跨进程通信,我们再梳理一下整体流程。
流程梳理
一、初始化
1、service_manager进程创建之后,会进行binder的初始化:
(1)通过binder_open打开dev/binder,创建binder_proc来记录进程信息,并通过mmap进行内存映射;
(2)通过binder_become_context_manager注册为binder的管理者,即将自己赋值给全局变量全局变量binder_context_mgr_node;
(3)通过binder_loop循环,等待消息,由于刚刚创建,没有进行中待处理任务,阻塞进程,等待唤醒。
2、system_server进程创建后,也会进行binder初始化:
(1)通过ProcessState打开dev/binder,创建binder_proc来记录进程信息,并通过mmap进行内存映射;
(2)通过开启新的线程,并调用IPCThreadState的joinThreadPool开启循环,等待接收消息,由于没有待处理的任务,该线程阻塞,等待唤醒。
二、进程通信
1、BpBinder的获取
binder通信,需要知道通信的目标是谁,在binder中定义binder_context_mgr_node的handle = 0,因此就通过handle = 0找到servicemanager,在BpBinder创建时持有了handle。
2、以AMS注册为例,数据发送
(1)通过Parcel将AMS数据包装,在此设置type为BINDER_TYPE_BINDER,并将AMS数据写入对应结构,再通过BpBinder的transact调用IPCThreadState的transact进行通信;
(2)在IPCThreadState的waitForResponse中,会调用binder驱动进行如下操作:
在第5步创建事务时,事物的数据地址直接通过地址偏移量计算出来,省去一次拷贝。
<1>查找/创建binder_thread
<2>找到servicemanager的binder_node
<3>查找/创建AMS的binder_node
<4>查找/创建AMS的binder_ref
<5>新建任务加入servicemanager队列中
<6>唤醒servicemanager进程
<7>创建任务告诉自己已经发送成功
(3)如上操作会唤醒servicemanager进程,servicemanager进程会对任务进行处理,同时发送回执
<1>找到AMS的binder_thread
<2>新建任务加入AMS队列中
<3>唤醒ssystem_server进程
<4>创建任务告诉自己已经发送成功
(4)第(3)步操作会唤醒system_server线程,system_server处理回执消息,退出waitForResponse,数据交互流程完毕。
数据结构
binder_proc
在binder驱动中,用来描述进程的上下文信息;每当进程打开文件节点/dev/binder时,binder驱动都会为这个进程创建一个binder_proc。
struct binder_proc {
struct hlist_node proc_node;
struct rb_root threads; // binder_thread红黑树
struct rb_root nodes; // binder_node组成的红黑树
struct rb_root refs_by_desc; // binder_ref组成的红黑树,根据句柄排序
struct rb_root refs_by_node; // binder_ref组成的红黑树,根据binder_node排序
int pid;
struct vm_area_struct *vma;
struct mm_struct *vma_vm_mm;
struct task_struct *tsk;
struct files_struct *files;
struct hlist_node deferred_work_node;
int deferred_work;
// 通过buffer + user_buffer_offset便能计算出用户空间的地址
void *buffer; // 物理内存在内核空间的起始位置
ptrdiff_t user_buffer_offset; // 内核空间和用户空间的偏移量
struct list_head buffers;
struct rb_root free_buffers;
struct rb_root allocated_buffers;
size_t free_async_space;
struct page **pages; // 映射的内存页数
size_t buffer_size; // 映射的内存大小
uint32_t buffer_free;
struct list_head todo; // 进程待处理队列
wait_queue_head_t wait;
struct binder_stats stats;
struct list_head delivered_death;
int max_threads;
int requested_threads;
int requested_threads_started;
int ready_threads;
long default_priority;
struct dentry *debugfs_entry;
};
binder_thread
描述线程相关的数据。
struct binder_thread {
struct binder_proc *proc; // 进程信息
struct rb_node rb_node;
int pid;
int looper; // 进程状态BINDER_LOOPER_STATE_ENTERED
struct binder_transaction *transaction_stack; // 正在处理的事务
struct list_head todo; // 待处理的链表
uint32_t return_error; /* Write failed, return error code in read buf */
uint32_t return_error2; /* Write failed, return error code in read */
/* buffer. Used when sending a reply to a dead process that */
/* we are also waiting on */
wait_queue_head_t wait;
struct binder_stats stats;
};
binder_node
在binder驱动中,会为每一个服务创建一个binder_node,通过它可以找到真正提供服务的对象。
struct binder_node {
int debug_id;
struct binder_work work;
union {
struct rb_node rb_node;
struct hlist_node dead_node;
};
struct binder_proc *proc; // 所属的进程信息
struct hlist_head refs; // binder_ref组成的链表
int internal_strong_refs;
int local_weak_refs;
int local_strong_refs;
binder_uintptr_t ptr; // 真正提供服务的对象地址,如AMS
binder_uintptr_t cookie; // 真正提供服务的对象数据,如AMS数据
unsigned has_strong_ref:1;
unsigned pending_strong_ref:1;
unsigned has_weak_ref:1;
unsigned pending_weak_ref:1;
unsigned has_async_transaction:1;
unsigned accept_fds:1;
unsigned min_priority:8;
struct list_head async_todo;
};
binder_ref
binder驱动中,需要通过binder_ref找到binder_node(服务对应的实体),每个与binder_node对应的客户端都会创建一个binder_ref;
struct binder_ref {
/* Lookups needed: */
/* node + proc => ref (transaction) */
/* desc + proc => ref (transaction, inc/dec ref) */
/* node => refs + procs (proc exit) */
int debug_id;
struct rb_node rb_node_desc;
struct rb_node rb_node_node;
struct hlist_node node_entry;
struct binder_proc *proc; // 进程
struct binder_node *node; // binder_node
uint32_t desc; // handle
int strong;
int weak;
struct binder_ref_death *death;
};