您的位置:首页 > 理论基础 > 数据结构算法

Android Binder 机制初步学习 笔记(一)—— 概述及数据结构介绍

2017-09-25 15:08 615 查看
NOTE

Binder 机制简介
Binder 基础数据结构分析
binderc
1 struct binder_work

2 struct binder_node

3 struct binder_ref_death

4 struct binder_ref

5 struct binder_buffer

6 struct binder_proc

7 struct binder_thread

8 struct binder_transaction

binderh
1 struct binder_write_read

2 enum BinderDriverCommandProtocol

3 enum BInderDriverReturnProtocol

4 struct binder_ptr_cookie

5 struct binder_transaction_data

6 struct flat_binder_object

NOTE

源码版本:Android 7.1.2。

内核版本:android-goldfish-3.4

内核下载:
git clone https://aosp.tuna.tsinghua.edu.cn/kernel/goldfish.git[/code] (清华镜像站)

以下分析思路均来自老罗的《Android 系统源代码情景分析(修订版)》

Binder 机制简介

Linux 内核提供了多种进程间通讯机制:

Pipe:管道。

Signal:信号。

Message:消息队列。

Share Memory:共享内存。

Socket:插口。

Android 虽是基于 Linux 内核而开发的,但并没有采用这些传统通讯机制,而是自己开发了一套新的机制,即
Binder


Binder
优势:

进程间传输数据时仅执行一次拷贝操作。

因此提高了效率,同时节省了空间。

Binder
机制中的关键词:

OpenBinder
Binder
机制是在它的基础上实现的。(Wiki:OpenBinder

CS 通讯方式:客户端
Client
/ 服务端
Server


Server 进程:提供服务
Service
的进程。

Client 进程:访问服务的进程。

Service 组件:同一个
Server
可以运行多个组件向
Client
提供服务,提供服务的组件即
Service
组件。

Service 代理对象:同一个
Client
可以同时向多个
Server
请求服务,每个请求都对应有一个
Client
组件,这个组件即是
Service
代理对象。

Binder 线程池:每个
Server
Client
进程都会维护一个
Binder
线程池来处理进程间通讯请求,
service
的提供与访问是可并发的。

Binder 驱动程序:向用户空间暴露一个设备文件
/dev/binder
,使应用程序进程可以间接通过它建立通信通道。

Service Manager 组件

Service
组件启动,就会将自己注册到一个
Service Manager
中,以便
Client
组件可以找到它。

可称为
Binder
机制的上下文管理者。

可看做一个特殊的
Service
组件。

open:系统接口,用于打开
Binder
设备。

mmap:系统接口,提供内存映射操作。

ioctl:系统接口,提供内核缓冲区管理操作,可实现读、写功能。

Client
Service
Service Manager
Binder
关系:


Client
Service
Service Manager
运行在用户空间。

Binder
驱动程序运行在内核空间。

系统提供
Service Manager
Binder


Client
Service
由应用程序实现。

通过
open
mmap
ioctl
Binder
设备交互。



Binder 基础数据结构分析

NOTE

结构体中经常能看到成员变量
debug_id
,它是用来标识
Binder
实体对象身份,帮助调试
Binder
驱动的,下面的分析中这个就忽略掉。

数据结构介绍的部分内容比较多,我觉得在这部分,不用一开始就一一理清楚它们的详细用处,只需要大概了解每个结构体的用处就好。等到以后分析实现机制的时候,碰到不太了解的成员变量时再回头来看,这样能理解得比较深刻。

1. binder.c

位置:
kernel/goldfish/drivers/staging/android/binder.c


该文件中的结构体都是在
Binder
驱动程序内部进行使用的。

1.1 struct binder_work

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;
};


binder_work
结构用于描述待处理的工作项

工作项有可能属于一个进程,也可能属于某个线程。

成员变量

entry
:将该结构体嵌入到一个宿主结构中。

type
:描述工作项类型,可判断出该结构嵌入的宿主类型。

1.2 struct 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_p
4000
roc *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_node
结构描述一个
Binder
实体对象


每个
Service
组件在驱动中都对应一个
Binder
实体,描述它在内核中的状态。

Binder
驱动通过强 (弱)引用计数技术维护实体的生命周期。

成员变量

work
:即工作项。

proc
:指向一个
Binder
实体对象的宿主进程。

rb_node
:宿主进程用红黑树维护内部
Binder
实体,该变量则是红黑树中一个节点。

dead_node
:宿主进程死亡,这个
Binder
实体就通过该变量保存在全局
hash
表中。

ref


一个
Binder
实体可被多个
Client
组件引用,于是驱动用
binder_ref
结构描述这些引用关系。

将引用同一个
Binder
实体的所有引用保存在
hash
表中。

该成员变量用于描述这个
hash
表。

驱动通过它可知哪些
Client
组件引用了同一
Binder
实体。

internal_strong_refs
&&
local_strong_refs
:描述强引用计数。

local_weak_refs
:描述弱引用计数。

has_strong_ref
&&
has_weak_ref


一个
Binder
实体请求一个
Service
执行某一操作,则增加该
Service
组件的强(弱)引用计数。

相应地,
Binder
实体将它的这两个变量置为
1


pending_strong_ref
&&
pending_weak_ref


1
时,表明正处于
Binder
实体向
Service
组件请求改变引用计数的过程

0
时,表明上述过程结束

ptr
&&
cookie
:指向用户空间地址。

ptr
指向
Service
组件内部引用计数对象(weakref_impl 类型)地址。

cookie
指向该
Service
组件地址。

has_async_transaction
:描述
Binder
实体是否正在处理异步事务。(1 为是, 0 为否)

async_todo


异步事务队列。

异步事务优先级低于同步,表现为同同一时刻,一个
Binder
实体所有异步事务至多处理一个,其余等待。而同步事务无限制。

min_priority
:处理来自
Client
的请求时,所要求的处理线程(
Server
中的一个线程)应具备的最小线程优先级。

accept_fds
:表示是否可接收包含文件描述符的通讯数据(1 可以,0 不可)。

1.3 struct binder_ref_death

struct binder_ref_death {
struct binder_work work;
void __user *cookie;
};


binder_ref_death
用来描述一个
Service
组件的死亡接收通知:

Service
组件所在进程可能会意外崩溃。

Client
进程需要在引用的
Service
组件死亡时得到通知,以便做出相应处理。

驱动决定向
Client
发送组件死亡通知时,将该结构体封装成一个工作项,并设置相应
work
值,再加入到
Client
todo
队列中等待处理。

成员变量

work
:标志一个具体的死亡通知类型。

cookie
:保存负责接收死亡通知的对象地址。

1.4 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;
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_ref
结构用来描述一个
Binder
引用对象:

每个
Client
组件在
Binder
驱动中都对应一个引用对象,用于描述它在内核中状态。

驱动通过强(弱)引用计数技术来维护引用对象的生命周期。

成员变量

node
:描述引用对象所引用的
Binder
实体。

node_entry
:每个
Binder
实体都有一个
hash
表,该变量即是这个表的节点。

desc
:句柄,用于描述
Binder
引用对象。(其值在进程范围内唯一,所以在不同进程中可能有相同的句柄值存在)

proc
:指向引用对象的宿主进程。

rb_node_desc
&&
rb_node_node
:宿主进程用两个红黑树保存所有
Binder
引用对象,分别以句柄值和对应
Binder
实体地址作为关键字,这两个成员变量即为对应的树中节点。

strong
&&
weak
:强引用计数与弱引用计数。

death
:指向一个
Service
组件的死亡接收通知。

1.5 struct 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_buffer
结构描述一个内核缓冲区,用于进程间数据传输

成员变量

entry
:驱动中内核缓冲区列表的节点。

free
:表示是否为空闲缓冲区,
1
为是。

rb_node


进程用两个红黑树保存内核缓冲区信息。

free
1
,则该变量表示空闲红黑树的节点。

free
0
,表示正在使用的内存缓冲区红黑树节点。

transaction
:内核缓冲区正在交给哪个事务。

target_node
:正在使用缓冲区的
Binder
实体。

allow_user_free
:若值为
1
,当
Service
组件处理完该事务后,就会请求驱动程序释放该内存缓冲区。

async_transaction
:表示关联的是否是一个异步事务,是为
1
,否则为
0


data
:指向一块大小可变的数据缓冲区,这是通讯数据真正保存的地方。

offset_size
:偏移数组大小。用于记录
Binder
对象在缓冲区中位置。

data_size
:数据缓冲区大小。

1.6 struct binder_proc

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;
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_proc
结构描述一个正在使用
Binder
机制的进程。

成员变量

proc_node
:进程调用
open
打开
Binder
设备时,驱动会将其映射到
binder_proc
结构,并保存在全局
hash
表中,这个变量即是表中的节点。

pid
:进程的进程组
ID


tsk
:任务控制块。

files
:打开文件结构体数组。

buffer_size
:进程调用
mmap
Binder
设备映射到进程的地址空间,实际上这是请求驱动为它分配一块内核缓冲区,该成员变量即是缓冲区的大小。

buffer
:内核空间地址(驱动内部使用)。

vma
:用户空间地址(应用程序使用)。

user_buffer_offset
:上面两个地址的差值,用它可以通过一个地址找到另一个地址。

buffers
:由于
buffer
指向的是一块大的缓冲区,为方便管理将其分成若干小块,保存在一个列表中,按照地址从小到大顺序排列,而该变量则指向了列表的头部。

allocated_buffers
:描述一个红黑树,保存了正在使用的(已分配物理页面)的内核缓冲区。

free_buffers
:红黑树,保存了空闲的内核缓冲区。

buffer_free
:空闲内核缓冲区的大小。

free_async_space
:保存当前可用于保存异步事务数据的缓冲区大小。

thread
:一个红黑树的根节点,以线程
ID
作为关键字,组织进程的
Binder
线程池。

max_thread
:驱动最多可主动请求注册的线程数量。

ready_thread
:进程当前空闲
Binder
线程数。

todo
:待处理工作项队列。

wait
:等待队列,对应睡眠的空闲
BInder
线程。

default_priority
:默认优先级。

n
13b53
odes
:描述一个红黑树,以
Binder
实体的成员变量
ptr
为关键字。

refs_by_desc
:描述一个红黑树,以
Binder
引用对象的成员
desc
为关键字。

refs_by_node
:描述一个红黑树,以
Binder
引用对象的成员
node
为关键字。

delivered_death
:保存死亡通知工作项的队列。

stats
:统计进程数据(如接收到的进程间通信请求次数)。

deferred_work_node
:一个
hash
表,保存进程可延迟执行的工作项。

deferred_work
:描述该延迟工作项具体类型。

BINDER_DEFERRED_PUT_FILES
:与文件描述符关闭相关的延迟。

BINDER_DEFERRED_FLUSH
:与唤醒空闲
Binder
线程相关的延迟。

BINDER_DEFERRED_RELEASE
:与资源释放相关的延迟。

enum binder_deferred_state {
BINDER_DEFERRED_PUT_FILES    = 0x01,
BINDER_DEFERRED_FLUSH        = 0x02,
BINDER_DEFERRED_RELEASE      = 0x04,
};


1.7 struct binder_thread

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
};

struct binder_thread {
struct binder_proc *proc;
struct rb_node rb_node;
int pid;
int looper;
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_thread
结构描述了
Binder
线程池中的一个线程。

成员变量

proc
:指向宿主进程。

rb_node
:红黑树中的节点(进程用一个红黑树组织线程池中的线程)。

pid
:线程
ID


looper
:线程状态。

BINDER_LOOPER_STATE_REGISTERED
:驱动程序请求注册线程的情况。

BINDER_LOOPER_STATE_ENTERED
:应用程序主动注册线程的情况。

BINDER_LOOPER_STATE_EXITED
:线程退出时。

BINDER_LOOPER_STATE_INVALID
:异常情况。

BINDER_LOOPER_STATE_WAITING
:空闲状态。

BINDER_LOOPER_STATE_NEED_RETURN
:表示线程需要马上返回用户空间。

todo
:保存来自
Client
的请求(指定该线程处理)的队列。

transaction_stack
:描述事务的堆栈。

wait
:线程正在处理事务
T1
,同时需要其他线程处理另一个事务
T2
,此时它就会睡眠在
wait
队列中,直到
T2
处理完成。

return_error
&&
return_error2
:异常情况时返回的错误信息。

stats
:统计线程数据,如收到的通信请求次数。

1.8 struct binder_transaction

struct binder_transaction {
int debug_id;
struct binder_work work;
struct binder_thread *from;
struct binder_transaction *from_parent;
struct binder_proc *to_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;
};


binder_transaction
结构描述了进程间的通信过程:

通常称这个过程为事务

成员变量

need_reply
:区分事务是同步(值为 1)或异步(值为 0)。

from
:指向发起事务的线程(源线程)。

to_proc
:指向负责处理该事务的进程(目标进程)。

to_thread
:指向负责处理该事务的线程(目标线程)。

priority
:源线程优先级。

sender_euid
:用户
ID


saved_priority
:修改线程优先级时的原值存档。

buffer
:指向驱动为该事务分配的一块内核缓冲区。

code
&&
flag
:从进程间通信数据中拷贝而来,具体内容参考结构体
binder_transaction_data


from_parent
:描述事务所依赖的另一个事务。

to_parent
:描述目标线程下一个需要处理的事务。

2. binder.h

位置:
kernel/goldfish/drivers/staging/android/binder.h


2.1 struct binder_write_read

#define BINDER_WRITE_READ               _IOWR('b', 1, struct binder_write_read)

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_WRITE_READ
是最重要的
IO
控制命令,它控制读写操作。

binder_write_read
结构描述进程间通信过程中传输的数据。

成员变量

输入数据

write_buffer
:指向一个用户空间缓冲区,内容为要传输到驱动的数据。

write_size
:相应缓冲区大小。

write_consumed
:描述驱动从缓冲区中处理了多少字节数据。

输出数据

read_buffer
:指向一个用户空间缓冲区,内容为驱动返回到用户空间的结果数据。

read_size
:缓冲区大小。

read_consumed
:应用程序从缓冲区中处理的字节数量。

write_buffer
&&
read_buffer
格式

都是数组,数组每个元素都由一个通信协议代码及其通信数据组成。

命令协议代码

write_buffer
中使用的协议代码。

通过
BinderDriverCommandProtocol
定义。

返回协议代码

read_buffer
中使用的协议代码。

通过
BinderDriverReturnProtocol
定义。

结构图如下。



2.2 enum 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
*/
};


命令协议 – 枚举成员:

进程间请求执行操作

BC_TRANSACTION
:请求驱动将通信数据传递到目标进程。

BC_REPLY
:请求驱动将结果传递给源进程。

BC_ACQUIRE_RESULT
:当前驱动程序实现中不支持。

BC_FREE_BUFFER
:释放相应的内核缓冲区。

Binder 引用对象计数(根据句柄值获取对象):

BC_INCREFS
&&
BC_DECREFS
:增加/减少弱引用计数。

BC_ACQUIRE
&&
BC_RELEASE
:增加/减少强引用计数。

驱动第一次增加一个 Binder 实体引用计数

BR_ACQUIRE
(返回协议):请求对应
Service
进程增加相应
Service
组件强引用计数。

BR_INCREFS
(返回协议):请求对应
Service
进程增加相应
Service
组件弱引用计数。

BC_ACQUIRE_DONE
&&
BC_INCREFS_DONE
:返回操作结果给驱动。

BC_ATTEMPT_ACQUIRE
:当前驱动实现中不支持。

线程注册

BC_REGISTER_LOOPER
:线程将自己注册到驱动后,给驱动的通知。

BC_ENTER_LOOPER
:驱动主动请求进程注册新线程到线程池,线程成功注册后通知。

BC_EXIT_LOOPER
:线程退出,通知驱动注销线程。

死亡接收通知

BC_REQUEST_DEATH_NOTIFICATION
:向驱动注册关于它所引用的
Service
组件的死亡通知。

BC_CLEAR_DEATH_NOTIFICATION
:注销之前注册的死亡接收通知。

BC_DEAD_BINDER_DONE
:进程获得
Service
组件死亡通知时,告知驱动它已处理。

2.3 enum 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.
*/
};


返回协议 – 枚举成员:

BR_ERROR
:驱动处理应用某个请求时发生异常,则需通知应用进程。

BR_OK
:驱动成功处理应用请求后,通知应用进程。

Client 进程向 Server 进程发出通信请求

BR_TRANSACTION
:驱动通知
Server
处理请求。

BR_REPLY
:请求结果数据返回给
Client


BR_ACQUIRE_RESULT
:当前驱动实现中不支持。

BR_DEAD_REPLY
:驱动处理通信请求时,若目标死亡,则通知源进程。

BR_TRANSACTION_COMPLETE
:通知应用,对应的命令协议代码已接收,正在分发给目标进程或目标线程处理。

Service 组件引用计数

BR_INCREFS
&&
BR_DECREFS
:增加/减少弱引用计数。

BR_ACQUIRE
&&
BR_RELEASE
:增加/减少强引用计数。

BR_ATTEMPT_ACQUIRE
:当前驱动实现中不支持。

BR_NOOP
:通知应用程序执行一个空操作,它的存在是为了方便之后可以替换为
BR_SPAWN_LOOPER


BR_SPAWN_LOOPER
:驱动发现一个进程没有足够空闲
Binder
线程处理通信请求时,通知其增加一个新线程到
Binder
线程池中。

BR_FINISHED
:当前驱动实现中不支持。

死亡通知

BR_DEAD_BINDER
:驱动监测到一个
Service
组件死亡事件时,通知相应的
Client
进程。

BR_CLEAR_DEATH_NOTIFICATION_DONE
Client
通知驱动注销它之前所注册的一个死亡接收通知,驱动执行完注销操作后,通知该
Client


BR_FAILED_REPLY
:驱动处理一个进程发出的
BC_TRANSACTION
命令协议时,若发生异常,则通知源进程。

2.4 struct binder_ptr_cookie

struct binder_ptr_cookie {
void *ptr;
void *cookie;
};


binder_ptr_cookie
结构描述一个
Binder
实体,或描述一个
Service
组件的死亡接收通知。

成员变量

ptr


该结构描述
Binder
实体,则该变量与
binder_node
结构中
ptr
等同。

该结构描述
Service
死亡通知,则指向一个
Binder
引用对象句柄值。

cookie


该结构描述
Binder
实体,则该变量与
binder_node
结构中
cookie
等同。

该结构描述
Service
死亡通知,则指向一个用于接收死亡通知的对象的地址。

2.5 struct binder_transaction_data

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 */
};

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_transaction_data
描述进程间传输的数据。

成员变量

target


描述一个目标
Binder
实体:

ptr
:指向该实体对应的一个
Service
组件内部的一个弱引用计数对象(weakref_impl)地址。

描述一个目标
Binder
引用:

handle
:指向该引用的句柄值。

cookie
:由应用程序指定的额外参数。驱动使用
BR_TRANSACTION
向一个
Server
发出请求时才有意义,指向的是目标
Service
组件地址。

code
:通信的两个进程相互约定好的通信代码。

flag
:描述进程通信行为特征,取值为
enum transaction_flags


TF_ONE_WAY
:置
1
时,表示是异步进程间通信。

TF_ROOT_OBJECT
:未启用。

TF_STATUS_CODE
:置
1
时,表示成员变量
data
描述的数据缓冲区内容是一个
4
字节状态码。

TF_ACCEPT_FDS
:置
0
时,表示源进程不允许目标进程返回结果中包含文件描述符。

发起通信请求的进程:

sender_pid
:进程
PID


sender_euid
:进程
UID


data_size
&&
data_offset
:描述通信数据缓冲区大小及偏移量。

data
:指向一个通信数据缓冲区

buf
:通信数据较小时用该静态数组传输。

ptr
:通信数据较大时用该动态分配的缓冲区传输

buffer
:指向一个数据缓冲区,保存通信数据。

offsets
:缓冲区中包含
Binder
对象,则用其描述每个对象的位置。

数据缓冲区中每个
Binder
对象都使用一个
flat_binder_object
结构描述,布局结构图如下。



2.6 struct flat_binder_object

#define B_PACK_CHARS(c1, c2, c3, c4) \
((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4))
#define B_TYPE_LARGE 0x85


enum {
BINDER_TYPE_BINDER      = B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE),
BINDER_TYPE_WEAK_BINDER = B_PACK_CHARS('w', 'b', '*', B_TYPE_LARGE),
BINDER_TYPE_HANDLE      = B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE),
BINDER_TYPE_WEAK_HANDLE = B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE),
BINDER_TYPE_FD          = B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE),
};


/*
* This is the flattened representation of a Binder object for transfer
* between processes.  The 'offsets' supplied as part of a binder transaction
* contains offsets into the data where these structures occur.  The Binder
* driver takes care of re-writing the structure type and data as it moves
* between processes.
*/
struct flat_binder_object {
/* 8 bytes for large_flat_header. */
unsigned long           type;
unsigned long           flags;

/* 8 bytes of data. */
union {
void            *binder;        /* local object */
signed long     handle;         /* remote object */
};

/* extra data associated with local object */
void                    *cookie;
};


flat_binder_object
结构可以描述(根据
type
区分):

一个
Binder
实体对象。

一个
Binder
引用对象。

一个文件描述符。

成员变量

type
:取值范围与顶部的宏定义及枚举有关

BINDER_TYPE_BINDER
:描述强类型
Binder
实体。

BINDER_TYPE_WEAK_BINDER
:描述弱类型
Binder
实体。

BINDER_TYPE_HANDLE
:描述强类型
Binder
引用。

BINDER_TYPE_WEAK_HANDLE
:描述弱类型
Binder
引用。

BINDER_TYPE_FD
:描述文件描述符。

flag
:标志值,当结构描述
Binder
实体时有意义

0 ~ 7
位:描述
Binder
实体处理通信请求时,它运行的线程的最小线程优先级。

8
位:描述
Binder
实体是否可将一块包含文件描述符的数据传输给目标进程。

结构体描述
Binder
实体:

binder
:指向实体对应的一个
Service
组件内部的一个弱引用计数对象的地址。

cookie
:指向该
Service
组件地址。

结构体描述
Binder
引用:

handle
:描述该引用对象的句柄值。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息