由于这部分内容相对复杂,我们将其拆解为几部分来讲解,这里我们先来了解一下背景知识和相关的基础数据结构。
Binder做为Android中进程间高效通信的核心组件,其底层是以misc设备驱动的形式实现的,但它本身并没有实现read
,write
操作,所有的控制都是通过ioctl
操作来实现。ioctl
是Linux中常见的系统调用,它是系统提供给应用的对底层设备特性进行控制的用户态接口,应用程序在调用ioctl
进行设备控制时,最后会调用到设备注册struct file_operations
结构体对象时的unlocked_ioctl
或者compat_ioctl
两个钩子上,具体是调用哪个钩子判断标准如下:
compat_ioctl
: 32位的应用运行在64位的内核上,这个钩子被调用。unlocked_ioctl
: 64位的应用运行在64位的内核或者32位的应用运行在32位的内核上,则调用这个钩子。在Binder驱动的struct file_operations
定义中,它compat_ioctl
和unlocked_ioctl
两个钩子的的实现都是对应到binder_ioctl
上的。
static const struct file_operations binder_fops = {
.owner = THIS_MODULE,
.poll = binder_poll,
.unlocked_ioctl = binder_ioctl,
.compat_ioctl = binder_ioctl,
.mmap = binder_mmap,
.open = binder_open,
.flush = binder_flush,
.release = binder_release,
};
接下来,我们来先看看binder_ioctl
的实现有关的结构体。
struct binder_thread
struct binder_thread {
struct binder_proc *proc; /*该thread相关联的binder_proc*/
struct rb_node rb_node; /*用于链入proc的threads红黑树*/
int pid;
int looper; /* 状态标识位,用于表示当前线程所处的状态,具体包括以下几种状态:
* enum {
* BINDER_LOOPER_STATE_REGISTERED = 0x01, /*进程的非主线程进入Binder循环状态*/
* BINDER_LOOPER_STATE_ENTERED = 0x02, /*进程的主线程进入Binder循环状态*/
* BINDER_LOOPER_STATE_EXITED = 0x04, /*线程退出Binder循环状态*/
* BINDER_LOOPER_STATE_INVALID = 0x08, /*线程处在一个无效的状态,表示出错*/
* BINDER_LOOPER_STATE_WAITING = 0x10, /*线程的todo队列为空,进入等待请求的状态*/
* BINDER_LOOPER_STATE_NEED_RETURN = 0x20 /*线程是否需要返回数据给进程的用户态*/
* };
*/
struct binder_transaction *transaction_stack; /*该线程的事务栈。通过struct binder_transaction的
* from_parent和to_parent分别链入客户端和服务端线程的
* transaction_stack事务栈中(即本字段)。详见2.7 */
struct list_head todo; /*binder_work队列,管理本线程所有待处理的binder_work*/
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 。发送reply时发生错误,该错误码用于返回给发送进程 */
wait_queue_head_t wait; /*binder线程空闲时,用于等待队列相关的结构,是Linux内核的一个数据结构*/
struct binder_stats stats; /*统计有关的结构*/
};
struct binder_proc
中的相关成员struct binder_proc{
...
struct rb_root threads; /*管理thread的红黑树根节点,以线程的id为序*/
struct rb_root nodes; /*管理binder_node的红黑树根节点,以binder_node中的ptr大小为序*/
struct rb_root refs_by_desc; /*管理binder_ref的红黑树根节点,以binder_ref中的desc大小为序*/
struct rb_root refs_by_node; /*管理binder_ref的红黑树根节点,以binder_ref对应的binder_node的地址为序*/
...
int max_threads; /*最大线程数*/
...
};
struct binder_write_read
struct binder_write_read {
/* process ----> kernel */
binder_size_t write_size; /* bytes to write, 进程用户态地址空间传递到内核数据的大小*/
binder_size_t write_consumed; /* bytes consumed by driver 进程用户态地址空间传递到内核数据中已经被内核态处理的大小*/
binder_uintptr_t write_buffer; /*进程用户态地址空间传递到内核数据的起始地址*/
/* kernel ----> process */
binder_size_t read_size; /* bytes to read, 总共可供给驱动写入的字节数,read_buffer可供内核使用的大小*/
binder_size_t read_consumed; /* bytes consumed by driver, 内核Binder驱动发送给用户态进程的字节数*/
binder_uintptr_t read_buffer; /*内核驱动发送给进程数据buffer的起始地址*/
};
struct 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; /*每个binder_ref的唯一标识符,主要用于debug*/
struct rb_node rb_node_desc; /*用来链入proc->refs_by_desc红黑树中,该红黑树以desc域为序组织的*/
struct rb_node rb_node_node; /*用来链入proc->refs_by_node红黑树中, 该红黑树以该binder_ref所对应的binder_node的地址为序组织的*/
struct hlist_node node_entry; /*用来链入binder_node的refs哈希链表中。*/
struct binder_proc *proc; /*指向该binder_ref中所属的binder_proc*/
struct binder_node *node; /*指向该binder_ref所对应(引用)的binder_node*/
uint32_t desc; /*binder_ref的描述符。用来返回给进程用户态地址空间,标识所对应的binder_ref*/
int strong; /*强引用计数*/
int weak; /*弱引用计数*/
struct binder_ref_death *death; /*Binder“死亡讣告”相关的一个结构体,详见:2.8*/
};
struct binder_node
struct binder_node {
int debug_id;
struct binder_work work;
union {
struct rb_node rb_node; /*用来链入proc的nodes红黑树,该红黑树以binder_node的ptr的大小为序*/
struct hlist_node dead_node;
};
struct binder_proc *proc;
struct hlist_head refs; /*所有引用这个binder_node的binder_ref通过它的node_entry加入这个哈希链表中,
* 这样binder_node通过查看这个哈希链表就知道有哪些binder_ref在引用它*/
int internal_strong_refs; /*binder_ref的强引用计数,即有多少个binder_ref强引用这个binder_node*/
int local_weak_refs; /*BBinder弱引用计数*/
int local_strong_refs; /*binder_buffer.target_node及BBinder的强引用计数*/
binder_uintptr_t ptr; /*对应BBinder基类RefBase中mRef成员的的地址,它是一个引用计数器,类型为weakref_impl*/
binder_uintptr_t cookie; /*对应BBinder的地址*/**
unsigned has_strong_ref:1; /*标识是否已经增加了用户态对应binder service(BBinder)对象的强引用计数*/
unsigned pending_strong_ref:1; /*标识是否有未处理的BR_ACQUIRE命令,在执行BR_ACQUIRE请求命令前设为1,在BC_ACQUIRE_DONE中设为0*/
unsigned has_weak_ref:1; /*标识是否已经增加了用户态对应binder service(BBinder)对象的弱引用计数*/
unsigned pending_weak_ref:1; /*标识是否有未处理的BR_INCREFS命令,在执行BR_INCREFS请求命令前设为1,在BC_INCREFS_DONE中设为0*/
unsigned has_async_transaction:1; /*标识是否有异步事务要处理。异步事务的含义是:客户端发送了带有TF_ONE_WAY标识的请求。*/
unsigned accept_fds:1; /*是否接受文件描述符*/
unsigned min_priority:8;
struct list_head async_todo; /*异步事务待处理链表*/
};
struct binder_transaction_data
struct binder_transaction_data {
/* The first two are only used for bcTRANSACTION and brTRANSACTION,
* identifying the target and contents of the transaction.
*/
union {
/* target descriptor of command transaction */
__u32 handle;
/* target descriptor of return transaction */
binder_uintptr_t ptr;
} target;
binder_uintptr_t cookie; /* target object cookie */
__u32 code; /* transaction command */
/* General information about the transaction. */
__u32 flags; /*标志位,如:TF_ONE_WAY*/
pid_t sender_pid; /*发送者进程id*/
uid_t sender_euid; /*发送者有效用户id*/
binder_size_t data_size; /* number of bytes of data */
binder_size_t offsets_size; /* number of bytes of offsets */
/* If this transaction is inline, the data immediately
* follows here; otherwise, it ends with a pointer to
* the data buffer.
*/
union { /*存放事务的数据部分,如果是inline,则数据直接放在buf数组中;
* 如果不是,则放在ptr结构体中的buffer和offsets的指针中。一般情况都是通过ptr结构体*/
struct {
/* transaction data */
binder_uintptr_t buffer;
/* offsets from buffer to flat_binder_object structs */
binder_uintptr_t offsets;
} ptr;
__u8 buf[8]; /*inline数据直接放在这个buf中, 在4.0.9的内核中,这个字段没有看见使用的地方*/
} data;
};
struct binder_transaction
struct binder_transaction {
int debug_id;
struct binder_work work; /*用于链入线程/进程todo队列的成员*/
struct binder_thread *from; /*事务发起线程thread的地址,如果是binder server回复给client,该域为NULL*/
struct binder_transaction ***from_parent**; /* 用于链入事务发起线程的事务栈中,
* 加入的时机是binder_transaction_data传入驱动并被binder_transaction处理的时候*/
struct binder_proc *to_proc; /*目标线程的proc地址*/
struct binder_thread *to_thread; /*事务目标线程thread的地址*/
struct binder_transaction *to_parent; /* 用于链入目标线程的事务栈中,
* 加入的时机是目标线程在调用binder_thread_read处理thread->todo队列
* 类型为BINDER_WORK_TRANACTION的binder_work时*/
unsigned need_reply:1;
/* unsigned is_dead:1; */ /* not used at the moment */
struct binder_buffer *buffer; /*存储数据的地方*/
unsigned int code; /*一个binder调用所对应的代号*/
unsigned int flags;
long priority; /*请求/回复 线程的优先级*/
long saved_priority; /*存储线程优先级备份,当需要修改一个线程的优先级时,先将它当前值放在该变量中,以便于稍后恢复。*/
kuid_t sender_euid;
};
进程用户态传输进来的struct binder_transaction_data
到内核态后,会转化成相应的struct binder_transaction
。该数据结构主要用于承载Binder请求和回复通信中的数据。
binder_ref_death
struct binder_ref_death {
struct binder_work work; /*binder service死亡时,通过该work的entry域链入thread或者proc的todo队列*/
binder_uintptr_t cookie; /*binder service死亡时,要通知的BpBinder对象的地址*/
};