Android5.1.1 Binder机制
Binder是Android系统提供的一种IPC机制,由于基于Linux内核所以除了Binder意外还有其它IPC机制如:管道,Socket等。
Binder驱动程序中,binder_work表示在Binder驱动中进程索要处理的工作项:
struct binder_work {
struct list_head entry;
enum {
BINDER_WORK_TRANSACTION = 1,
BINDER_WORK_TRANSACTION_COMPLETE,
BINDER_WORK_NODE,
BINDER_WORK_DEAD_BINDER,
BINDER_WORK_DEAD_BINDER_AND_CLEAR,
BINDER_WORK_CLEAR_DEATH_NOTIFICATION,
} type;
};
entry被定义为list_head类型,用于实现一个双向链表,存储所有binder_work队列;还包含一个enum类型的type:binder_work。
结构体binder_node用来定义Binder实体对象:
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;
int internal_strong_refs;
int local_weak_refs;
int local_strong_refs;
void __user *ptr;
void __user *cookie;
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实体隶属于提供实体的进程。binder_node说明:
binder_ref_death同志结构体。只要某一进程对某一binder引用订阅了其实体的死亡通知,那么binder都启动将会成为此binder引用建立一个binder_ref_death通知结构体,将其保存在当前进程的对应binder引用结构体的death域中:
struct binder_ref_death {
struct binder_work work;
void __user *cookie;
};
结构体binder_ref描述一个Binder引用对象:
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;
uint32_t desc;
int strong;
int weak;
struct binder_ref_death *death;
};
结构体binder_buffer描述一个内核缓冲区,能在进程间传输数据:
struct binder_buffer {
struct list_head entry; /* free and allocated entries by address */ //构建一个双向链表
struct rb_node rb_node; /* free entry by size or allocated entry */ //表示一个红黑树节点
/* by address */
unsigned free:1;
unsigned allow_user_free:1;
unsigned async_transaction:1;
unsigned debug_id:29;
struct binder_transaction *transaction; //中转请求和返回结果
struct binder_node *target_node; //一个目标节点
size_t data_size; //数据大小
size_t offsets_size; //偏移量
uint8_t data[0]; //存储实际数据
};
结构体binder_proc表示症状使用Binder进程通信机制的进程,能够保存调用Binder的各个进程或线程的信息:
struct binder_proc {
struct hlist_node proc_node; //实现双向链表
struct rb_root threads; //储存所有进程信息
struct rb_root nodes;
struct rb_root refs_by_desc;
struct rb_root refs_by_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;
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; //Binder状态
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存储每一个单独的线程的信息,表示Binder线程池中的一个线程:
struct binder_thread {
struct binder_proc *proc; //当前线程属于哪一个Binder进程(binder_porc指针)
struct rb_node rb_node; //红黑树节点
int pid; //线程pid
int looper; //线程状态信息
struct binder_transaction *transaction_stack;//定义要接收发送的进/线程信息binder_transaction
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; //等待队列头结构binder_stats
struct binder_stats stats;
};
enum {
BINDER_LOOPER_STATE_REGISTERED = 0x01,
BINDER_LOOPER_STATE_ENTERED = 0x02,
BINDER_LOOPER_STATE_EXITED = 0x04,
BINDER_LOOPER_STATE_INVALID = 0x08,
BINDER_LOOPER_STATE_WAITING = 0x10,
BINDER_LOOPER_STATE_NEED_RETURN = 0x20
};
looper表示的线程状态信息枚举定义:0x01,0x02,0x04,0x08,0x10,0x20(注册、进入、退出、销毁、等待、需要返回)
结构体binder_transaction中转请求和返回结果,并保存接受和要发送的进程信息:
struct binder_transaction {
int debug_id; //调试相关
struct binder_work work; //binder_work
struct binder_thread *from; //binder_thread对象
struct binder_transaction *from_parent; //接收进程信息的父节点
struct binder_proc *to_proc; //binder_proc类型结构体
struct binder_thread *to_thread; //发送进程信息的父节点
struct binder_transaction *to_parent;
unsigned need_reply:1;
/* unsigned is_dead:1; */ /* not used at the moment */
struct binder_buffer *buffer;
unsigned int code;
unsigned int flags;
long priority;
long saved_priority;
uid_t sender_euid; /*ender_euid表示要发送进程对文件和资源的操作权限(euid表示进程对文件和资源的访问权限)*/
};
binder_transaction中还包含了类型类inder_buffer的一个buffer,用来表示Binder的缓冲区信息
在.h文件中
结构体binder_write_read表示在进程之间的通信过程中传输的数据,数据包中有一个cmd域用于区分不同的请求:
struct binder_write_read {
signed long write_size; /* bytes to write */ //写入数据大小
signed long write_consumed; /* bytes consumed by driver */ //被消耗的写数据大小
unsigned long write_buffer;
signed long read_size; /* bytes to read */ //读入数据大小
signed long read_consumed; /* bytes consumed by driver */ //被消耗的读数据大小
unsigned long read_buffer;
};
当Binder驱动找到处理此事件的进程后,Binder驱动就会把需要处理的事件的任务放在读缓冲(binder_write_read)里,返回给这个服务线程,改服务线程则会执行指定命令的操作;处理请求的线程把数据交给合适的对象来执行预定操作,然后返回结果同样结构binder_transaction_data进行封装,以写命令的方式传回给Binder驱动,并将此数据放在一个读缓冲(binder_write_read)里,返回正在等待结果的原进程(线程),这样就完成一次通信
结构体binder_write_read包含的命令在BinderDriverCommandProtocol中定义:
enum BinderDriverCommandProtocol {
BC_TRANSACTION = _IOW('c', 0, struct binder_transaction_data), /*用于翻译和解析将要被处理的事件数据*/
BC_REPLY = _IOW('c', 1, struct binder_transaction_data),/*事件处理完成之后对返回“结果数据”的操作指令*/
/*
* binder_transaction_data: the sent command.
*/
BC_ACQUIRE_RESULT = _IOW('c', 2, int),
/*
* not currently supported
* int: 0 if the last BR_ATTEMPT_ACQUIRE was not successful.
* Else you have acquired a primary reference on the object.
*/
BC_FREE_BUFFER = _IOW('c', 3, int),
/*
* void *: ptr to transaction data received on a read
*/
BC_INCREFS = _IOW('c', 4, int),
BC_ACQUIRE = _IOW('c', 5, int),
BC_RELEASE = _IOW('c', 6, int),
BC_DECREFS = _IOW('c', 7, int),
/*
* int: descriptor
*/
BC_INCREFS_DONE = _IOW('c', 8, struct binder_ptr_cookie),
BC_ACQUIRE_DONE = _IOW('c', 9, struct binder_ptr_cookie),
/*
* void *: ptr to binder
* void *: cookie for binder
*/
BC_ATTEMPT_ACQUIRE = _IOW('c', 10, struct binder_pri_desc),
/*
* not currently supported
* int: priority
* int: descriptor
*/
BC_REGISTER_LOOPER = _IO('c', 11),
/*
* No parameters.
* Register a spawned looper thread with the device.
*/
BC_ENTER_LOOPER = _IO('c', 12),
BC_EXIT_LOOPER = _IO('c', 13),
/*
* No parameters.
* These two commands are sent as an application-level thread
* enters and exits the binder loop, respectively. They are
* used so the binder can have an accurate count of the number
* of looping threads it has available.
*/
BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct binder_ptr_cookie),
/*
* void *: ptr to binder
* void *: cookie
*/
BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_ptr_cookie),
/*
* void *: ptr to binder
* void *: cookie
*/
BC_DEAD_BINDER_DONE = _IOW('c', 16, void *),
/*
* void *: cookie
*/
};
在枚举BinderDriverReturnProtocol中定义了读操作命令协议:
enum BinderDriverReturnProtocol {
BR_ERROR = _IOR('r', 0, int),
/*
* int: error code
*/
BR_OK = _IO('r', 1),
/* No parameters! */
BR_TRANSACTION = _IOR('r', 2, struct binder_transaction_data),
BR_REPLY = _IOR('r', 3, struct binder_transaction_data),
/*
* binder_transaction_data: the received command.
*/
BR_ACQUIRE_RESULT = _IOR('r', 4, int),
/*
* not currently supported
* int: 0 if the last bcATTEMPT_ACQUIRE was not successful.
* Else the remote object has acquired a primary reference.
*/
BR_DEAD_REPLY = _IO('r', 5),
/*
* The target of the last transaction (either a bcTRANSACTION or
* a bcATTEMPT_ACQUIRE) is no longer with us. No parameters.
*/
BR_TRANSACTION_COMPLETE = _IO('r', 6),
/*
* No parameters... always refers to the last transaction requested
* (including replies). Note that this will be sent even for
* asynchronous transactions.
*/
BR_INCREFS = _IOR('r', 7, struct binder_ptr_cookie),
BR_ACQUIRE = _IOR('r', 8, struct binder_ptr_cookie),
BR_RELEASE = _IOR('r', 9, struct binder_ptr_cookie),
BR_DECREFS = _IOR('r', 10, struct binder_ptr_cookie),
/*
* void *: ptr to binder
* void *: cookie for binder
*/
BR_ATTEMPT_ACQUIRE = _IOR('r', 11, struct binder_pri_ptr_cookie),
/*
* not currently supported
* int: priority
* void *: ptr to binder
* void *: cookie for binder
*/
BR_NOOP = _IO('r', 12),
/*
* No parameters. Do nothing and examine the next command. It exists
* primarily so that we can replace it with a BR_SPAWN_LOOPER command.
*/
BR_SPAWN_LOOPER = _IO('r', 13),
/*
* No parameters. The driver has determined that a process has no
* threads waiting to service incomming transactions. When a process
* receives this command, it must spawn a new service thread and
* register it via bcENTER_LOOPER.
*/
BR_FINISHED = _IO('r', 14),
/*
* not currently supported
* stop threadpool thread
*/
BR_DEAD_BINDER = _IOR('r', 15, void *),
/*
* void *: cookie
*/
BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, void *),
/*
* void *: cookie
*/
BR_FAILED_REPLY = _IO('r', 17),
/*
* The the last transaction (either a bcTRANSACTION or
* a bcATTEMPT_ACQUIRE) failed (e.g. out of memory). No parameters.
*/
};
binder_ptr_cookie和binder_transaction_data
binder_ptr_cookie表示一个Binder实体对象或者Service组件的死亡接受通知:
struct binder_ptr_cookie {
void *ptr;
void *cookie;
};
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 {
size_t handle; /* target descriptor of command transaction */
void *ptr; /* target descriptor of return transaction */
} target;
void *cookie; /* target object cookie */
unsigned int code; /* transaction command */
/* General information about the transaction. */
unsigned int flags;
pid_t sender_pid;
uid_t sender_euid;
size_t data_size; /* number of bytes of data */
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 {
struct {
/* transaction data */
const void *buffer;
/* offsets from buffer to flat_binder_object structs */
const void *offsets;
} ptr;
uint8_t buf[8];
} data;
};
系统中,把在进程之间传递的数据成为Binder对象,在对应源代码中使用结构体flat_binder_object表示:
struct flat_binder_object {
/* 8 bytes for large_flat_header. */
unsigned long type; /*描述Binder类型,传输的数据是一个复用数据联合体。对Binder类型来说,数据是一个Binder本地对象*/
unsigned long flags; //传输方式,其值使用一个enum表示
/* 8 bytes of data. */
union {
void *binder; /* local object */
signed long handle; /* remote object */ //一个远程的handle句柄
};
/* extra data associated with local object */
void *cookie; //如果是本地对象,Binder还可以带有额外的数据,保存到cookie字段中
};
enum transaction_flags {
TF_ONE_WAY = 0x01, /* this is a one-way call: async, no return */
TF_ROOT_OBJECT = 0x04, /* contents are the component's root object */
TF_STATUS_CODE = 0x08, /* contents are a 32-bit status code */
TF_ACCEPT_FDS = 0x10, /* allow replies with file descriptors */
};