Android源码之Binder(二)

分析完Binder驱动程序的打开和内存分配的过程之后,我们看一下与Binder驱动程序的交互过程,这是通过调用ioctl函数来实现的。
当调用ioctl函数时,Binder驱动程序的binder_ioctl就会被调用。binder_ioctl的定义如下所示:
static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
[// static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
filp指向打开的文件结构体
cmd表示命令字,取值如下所列:
#define BINDER_WRITE_READ   _IOWR('b', 1, struct binder_write_read)
[// #define BINDER_WRITE_READ   _IOWR('b', 1, struct binder_write_read)
IO控制命令BINDER_WRITE_READ后面所跟的参数是一个binder_write_read结构体,它的定义如下:
结构体binder_write_read用来描述进程间通信过程中所传输的数据,这些数据包括输入数据和输出数据。
struct binder_write_read {
signed long write_size; /* bytes to write */
[// signed long write_size;
write_size指示write_buffer的大小,单位是字节
]// signed long write_size;
signed long write_consumed; /* bytes consumed by driver */
[// signed long write_consumed
write_consumed用来描述Binder驱动程序从缓冲区write_buffer中处理了多少字节的数据
]// signed long write_consumed
unsigned long write_buffer;
[// unsigned long write_buffer
write_buffer指向一个用户空间缓冲区的地址,里面保存的内容即为要传输到Binder驱动程序的数据。
]// unsigned long write_buffer
signed long read_size; /* bytes to read */
[// signed long read_size
read_size指示read_buffer的大小,单位是字节
]// signed long read_size
signed long read_consumed; /* bytes consumed by driver */
[// signed long read_consumed
read_consumed用来描述用户空间应用程序从缓冲区read_buffer中处理了多少个字节的数据
]// signed long read_consumed
unsigned long read_buffer;
[// unsigned long read_buffer
成员变量read_buffer也是指向一个用户空间缓冲区的地址,里面保存的内容即为Binder驱动程序返回给用户空间的进程间通信结果数据。
缓冲区write_buffer和read_buffer的数据格式都是一个数组。
数组的每一个元素都是由一个通信协议代码及其通信数据组成。协议代码又分为两种类型,其中一种是在输入缓冲区write_buffer中使用的,称为命令协议代码,另一种是在输出缓冲区read_buffer中使用的,称为返回协议代码。
命令协议代码通过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_REPLY = _IOW('c', 1, struct binder_transaction_data)
命令协议代码BC_TRANSACTION和BC_REPLY后面跟的通信数据使用一个结构体binder_transaction_data来描述。
当一个进程请求另外一个进程执行某一个操作时,源进程就使用命令协议代码BC_TRANSACTION来请求Binder驱动程序将通信数据传递到目标进程
当目标进程处理完成源进程所请求的操作之后,它就使用命令协议代码BC_REPLY来请求Binder驱动程序将结果数据传递给源进程。
binder_transaction_data的结构体定义如下:
struct binder_transaction_data {
union {
size_t handle; /* target descriptor of command transaction */
void *ptr; /* target descriptor of return transaction */
} target;
[// target
成员变量target是一个联合体,用来描述一个目标Binder实体对象或者目标Binder引用对象。
如果它描述的是一个目标Binder实体对象,那么它的成员变量ptr就指向与该Binder实体对象对应的一个Service组件内部的一个弱引用计数对象(weakref_impl)的地址。
如果它描述的是一个目标Binder引用对象,那么它的成员变量handle就指向该Binder引用对象的句柄值。
]// target
void *cookie; /* target object cookie */
[// void *cookie
成员变量cookie是由应用程序进程指定的额外参数。当Binder驱动程序使用返回命令协议BR_TRANSACTION向一个Server进程发出一个进程间通信请求时,这个成员变量才有实际意义,它指向的是目标Service组件的地址。
]// void *cookie
unsigned int code; /* transaction command */
[// unsigned int code
成员变量code是由执行进程间通信的两个进程互相约定好的一个通信代码,Binder驱动程序不关心它的含义。
]// unsigned int code

unsigned int flags;
[// unsigned int flags
成员变量flags是一个标志值,用来描述进程间通信行为特征,它的取值如下:
enum transaction_flags {
TF_ONE_WAY = 0x01, /* this is a one-way call: async, no return */
[// TF_ONE_WAY = 0x01
如果TF_ONE_WAY位被设置为1,就表示这是一个异步的进程间通信过程
]// TF_ONE_WAY = 0x01
TF_ROOT_OBJECT = 0x04, /* contents are the component's root object */
TF_STATUS_CODE = 0x08, /* contents are a 32-bit status code */
[// TF_STATUS_CODE = 0x08
如果成员变量flags的TF_STATUS_CODE位被设置为1,就表示成员变量data所描述的数据缓冲区的内容是一个4字节的状态码。
]// TF_STATUS_CODE = 0x08
TF_ACCEPT_FDS = 0x10, /* allow replies with file descriptors */
[// TF_ACCEPT_FDS = 0x10
如果成员变量TF_ACCEPT_FDS为被设置为0,就表示源进程不允许目标进程返回的结果数据中包含有文件描述符
]// TF_ACCEPT_FDS = 0x10
};
]// unsigned int flags
pid_t sender_pid;
uid_t sender_euid;
[// uid_t sender_euid
成员变量sender_pid和sender_euid表示发起进程间通信请求的进程的PID和UID.这两个成员变量的值是由Binder驱动程序来填写的,因此,目标进程通过这两个成员变量就可以识别出源进程的身份,以便进程安全检查。
]// uid_t sender_euid
size_t data_size; /* number of bytes of data */
size_t offsets_size; /* number of bytes of offsets */
[// size_t offsets_size
成员变量data_size和offsets_size分别用来描述一个通信数据缓冲区以及一个偏移数组的大小。
]// size_t offsets_size
union {
struct {
/* transaction data */
const void *buffer;
/* offsets from buffer to flat_binder_object structs */
const void *offsets;
} ptr;
uint8_t buf[8];
} data;
[// data
成员变量data是一个联合体,它指向一个通信数据缓冲区。当通信数据较小时,就直接使用联合体内静态分配的数组buf来传输数据
当通信数据较大时,就需要使用一块动态分配的缓冲区来传输数据。这块动态分配的缓冲区通过一个包含两个指针的结构体来描述,即通过联合体内的成员变量ptr来描述。
结构体ptr的成员变量buffer指向一个数据缓冲区,它是真正用来保存通信数据的,它的大小由前面所描述的成员变量data_size来指定。
当数据缓冲区包含有Binder对象时,那么紧跟在这个数据缓冲区的后面就会有一个偏移数据offsets,用来描述数据缓冲区中每一个Binder对象的位置。
有了这个偏移数据之后,Binder驱动程序就可以正确地维护其内部的Binder实体对象和Binder引用对象的引用计数。
]// data
};
[// struct binder_transaction_data
结构体binder_transaction_data用来描述进程间通信过程中所传输的数据。
]// struct binder_transaction_data
]// BC_REPLY = _IOW('c', 1, struct binder_transaction_data)

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_ACQUIRE_RESULT = _IOW('c', 2, int)
BC_ACQUIRE_RESULT命令协议代码目前系统不支持
]// BC_ACQUIRE_RESULT = _IOW('c', 2, int)

BC_FREE_BUFFER = _IOW('c', 3, int),
/*
* void *: ptr to transaction data received on a read
*/
[// BC_FREE_BUFFER = _IOW('c', 3, int)
命令协议代码BC_FREE_BUFFER后面跟的是一个整数,它指向了在Binder驱动程序内部所分配的一块内存缓冲区。
当目标进程处理完源进程的通信请求之后,它就会使用命令协议代码BC_FREE_BUFFER来通知Binder驱动程序来释放这个内核缓冲区。
]// BC_FREE_BUFFER = _IOW('c', 3, int)

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_DECREFS = _IOW('c', 7, int)
这四个命令协议代码后面跟的通信数据是一个整数,描述了一个Binder引用对象的句柄值。
其中,命令协议代码BC_INCREFS和BC_DECREFS分别用来增加和减少一个Binder引用对象的弱引用计数。
而命令协议代码BC_ACQUIRE和BC_RELEASE分别用来增加和减少一个Binder引用对象的强引用计数。
]// BC_DECREFS = _IOW('c', 7, int)

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_ACQUIRE_DONE = _IOW('c', 9, struct binder_ptr_cookie)
命令协议代码BC_INCREFS_DONE和BC_ACQUIRE_DONE后面跟的通信数据使用一个结构体binder_ptr_cookie来描述。
Binder驱动程序第一次增加一个Binder实体对象的强引用计数或者弱引用计数时,就会使用返回协议代码BR_ACQUIRE或者BR_INCREFS来请求对应的Server进程增加对应的Service组件的强引用计数或者弱引用计数。
当Server进程处理完成这两个请求之后,就会分别使用命令协议代码BC_INCREFS_DONE和BC_ACQUIRE_DONE将操作结果返回给Binder驱动程序。
结构体binder_ptr_cookie的定义如下;
struct binder_ptr_cookie {
void *ptr;
void *cookie;
};
[// struct binder_ptr_cookie
结构体binder_ptr_cookie用来描述一个Binder实体对象或者一个Service组件的死亡接收通知。
当结构体binder_ptr_cookie描述的是一个Binder实体对象时,成员变量ptr和cookie的含义等同于前面所介绍的结构体binder_node的成员变量ptr和cookie.
当结构体binder_ptr_cookie描述的是一个Service组件的死亡接收通知时,成员变量ptr指向的是一个Binder引用对象的句柄值,而成员变量cookie指向的是一个用来接收死亡通知的对象的地址。
]// struct binder_ptr_cookie
]// BC_ACQUIRE_DONE = _IOW('c', 9, struct binder_ptr_cookie)

BC_ATTEMPT_ACQUIRE = _IOW('c', 10, struct binder_pri_desc),
/*
* not currently supported
* int: priority
* int: descriptor
*/
[// BC_ATTEMPT_ACQUIRE = _IOW('c', 10, struct binder_pri_desc)
BC_ATTEMPT_ACQUIRE在当前的Binder驱动程序实现中不支持。
]// BC_ATTEMPT_ACQUIRE = _IOW('c', 10, struct binder_pri_desc)

BC_REGISTER_LOOPER = _IO('c', 11),
/*
* No parameters.
* Register a spawned looper thread with the device.
*/
[// BC_REGISTER_LOOPER = _IO('c', 11)
当Binder驱动程序主动请求进程注册一个新的线程到它的Binder线程池中来处理进程间通信请求之后,新创建的线程就会使用命令协议代码BC_REGISTER_LOOPER来通知Binder驱动程序,它准备就绪了。
]// BC_REGISTER_LOOPER = _IO('c', 11)

BC_ENTER_LOOPER = _IO('c', 12),
[// BC_ENTER_LOOPER = _IO('c', 12)
当一个线程将自己注册到Binder驱动程序之后,它接着就会使用命令协议代码BC_ENTER_LOOPER来通知Binder驱动程序,它已经准备就绪处理进程间通信请求了。
]// BC_ENTER_LOOPER = _IO('c', 12)
BC_EXIT_LOOPER = _IO('c', 13),
[// BC_EXIT_LOOPER = _IO('c', 13)
当一个线程要退出时,它就使用命令协议代码BC_EXIT_LOOPER从Binder驱动程序中注销,这样它就不会再接收到进程间通信请求了。
]// 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_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct binder_ptr_cookie)
命令协议代码BC_REQUEST_DEATH_NOTIFICATION后面跟的是binder_ptr_cookie结构体。
如果一个进程希望获得它所引用的Service组件的死亡接收通知,那么它就需要使用命令协议代码BC_REQUEST_DEATH_NOTIFICATION来向Binder驱动程序注册一个死亡接收通知
]// BC_REQUEST_DEATH_NOTIFICATION = _IOW('c', 14, struct binder_ptr_cookie)

BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_ptr_cookie),
/*
* void *: ptr to binder
* void *: cookie
*/
[// BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_ptr_cookie)
命令协议代码BC_CLEAR_DEATH_NOTIFICATION后面跟的也是一个binder_ptr_cookie结构体。
如果一个进程想注册之前所注册的一个死亡接收通知,那么它就需要使用命令协议代码BC_CLEAR_DEATH_NOTIFICATION来向Binder驱动程序发出请求
]// BC_CLEAR_DEATH_NOTIFICATION = _IOW('c', 15, struct binder_ptr_cookie)
BC_DEAD_BINDER_DONE = _IOW('c', 16, void *),
/*
* void *: cookie
*/
[// BC_DEAD_BINDER_DONE = _IOW('c', 16, void *)
命令协议代码BC_DEAD_BINDER_DONE后面跟的通信数据是一个void类型的指针,指向一个死亡接收通知结构体binder_ref_death的地址。当一个进程获得一个Service组件的死亡通知时,它就会使用命令协议代码BC_DEAD_BINDER_DONE来通知Binder驱动程序,它已经处理完成该Service组件的死亡通知了。
]// BC_DEAD_BINDER_DONE = _IOW('c', 16, void *)
};
而返回协议代码通过BinderDriverReturnProtocol来定义的:
enum BinderDriverReturnProtocol {
BR_ERROR = _IOR('r', 0, int),
/*
* int: error code
*/
[// BR_ERROR = _IOR('r', 0, int)
返回协议代码BR_ERROR后面跟的通信数据是一个整数,用来描述一个错误代码。Binder驱动程序在处理应用进程进程发出的某个请求时,如果发生了异常情况,它就会使用返回协议代码BR_ERROR来通知应用程序进程。
]// BR_ERROR = _IOR('r', 0, int)

BR_OK = _IO('r', 1),
/* No parameters! */
[// BR_OK = _IO('r', 1)
返回协议代码BR_OK后面不需要指定通信数据。Binder驱动程序成功处理了应用程序进程发出的某一个请求之后,它就会使用返回协议代码BR_OK来通知应用程序进程。
]// BR_OK = _IO('r', 1)

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_REPLY = _IOR('r', 3, struct binder_transaction_data)
返回协议代码BR_TRANSACTION和BR_REPLY后面跟的通信数据使用一个结构体binder_transaction_data来描述。当一个Client进程向一个Server进程发出进程间通信请求时,Binder驱动程序就会使用返回协议代码BR_TRANSACTION通知该Server进程来处理该进程间通信请求。
当Server进程处理完成该进程间通信请求之后,Binder驱动程序就会使用返回协议代码BR_REPLY将进程间通信请求结果数据返回给Client进程。
]// BR_REPLY = _IOR('r', 3, struct binder_transaction_data)
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_ACQUIRE_RESULT = _IOR('r', 4, int)
返回协议代码BR_ACQUIRE_RESULT在当前的Binder驱动程序中不支持。
]// BR_ACQUIRE_RESULT = _IOR('r', 4, int)

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_DEAD_REPLY = _IO('r', 5)
Binder驱动程序在处理进程间通信请求时,如果发现目标进程或者目标线程已经死亡,它就会使用返回协议代码BR_DEAD_REPLY来通知源进程。
]// BR_DEAD_REPLY = _IO('r', 5)

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_TRANSACTION_COMPLETE = _IO('r', 6)
当Binder驱动程序接收到应用程序进程给它发送的一个命令协议代码BC_TRANSACTION或者BC_REPLY时,它就会使用返回协议代码BR_TRANSACTION_COMPLETE来通知应用程序进程,该命令协议代码已经被接收,正在分发给目标进程或者目标线程处理。
]// BR_TRANSACTION_COMPLETE = _IO('r', 6)

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_DECREFS = _IOR('r', 10, struct binder_ptr_cookie)
返回协议代码BR_INCREFS, BR_ACQUIRE, BR_RELEASE和BR_DECREFS后面跟的通信数据使用一个结构体binder_ptr_cookie来描述,其中,命令协议代码BR_INCREFS和BR_DECREFS分别用来增加和减少一个Service组件的弱引用计数,而命令协议代码BR_ACQUIRE和BR_RELEASE分别用来增加和减少一个Service组件的强引用计数。
]// BR_DECREFS = _IOR('r', 10, struct binder_ptr_cookie)
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_ATTEMPT_ACQUIRE = _IOR('r', 11, struct binder_pri_ptr_cookie)
返回协议代码BR_ATTEMPT_ACQUIRE在当前的Binder驱动程序实现中不支持。
]// BR_ATTEMPT_ACQUIRE = _IOR('r', 11, struct binder_pri_ptr_cookie)
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_NOOP = _IO('r', 12)
返回协议代码BR_NOOP后面不需要指定通信数据。Binder驱动程序使用返回协议代码BR_NOOP来通知应用程序进程执行一个空操作,它的存在是为了方便以后可以替换为返回协议代码BR_SPAWN_LOOPER.
]// BR_NOOP = _IO('r', 12)
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_SPAWN_LOOPER = _IO('r', 13)
返回协议代码BR_SPAWN_LOOPER后面不需要指定通信数据。当Binder驱动程序发现一个进程没有足够的空闲Binder线程来处理进程间通信请求时,它就会使用返回协议代码BR_SPAWN_LOOPER来通知该进程增加一个新的线程到Binder线程池中。
]// BR_SPAWN_LOOPER = _IO('r', 13) 

BR_FINISHED = _IO('r', 14),
/*
* not currently supported
* stop threadpool thread
*/
[// BR_FINISHED = _IO('r', 14)
BR_FINISHED在当前的Binder驱动程序实现中不支持。
]// BR_FINISHED = _IO('r', 14)
BR_DEAD_BINDER = _IOR('r', 15, void *),
/*
* void *: cookie
*/
BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, void *),
/*
* void *: cookie
*/
[// BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, void *)
返回协议代码BR_DEAD_BINDER和BR_CLEAR_DEATH_NOTIFICATION_DONE后面跟的通信数据是一个void类型的指针,它指向一个用来接收Service组件死亡通知的对象的地址。
当Binder驱动程序检测到一个Service组件的死亡事件时,它就会使用返回协议代码BR_DEAD_BINDER来通知响应的Client进程。
当Client进程通知Binder驱动程序注销它之前所注册的一个死亡接收通知时,Binder驱动程序执行完成这个注销操作之后,就会使用返回协议代码BR_CLEAR_DEATH_NOTIFICATION_DONE来通知Client进程。
]// BR_CLEAR_DEATH_NOTIFICATION_DONE = _IOR('r', 16, void *)
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_FAILED_REPLY = _IO('r', 17)
当Binder驱动程序处理一个进程发出的BC_TRANSACTION命令协议时,如果发生了异常情况,它就会使用返回协议代码BR_FAILED_REPLY来通知源进程。
]// BR_FAILED_REPLY = _IO('r', 17)
};
]// unsigned long read_buffer
};
]// #define BINDER_WRITE_READ   _IOWR('b', 1, struct binder_write_read)
#define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, int64_t)
#define BINDER_SET_MAX_THREADS _IOW('b', 5, size_t)
#define BINDER_SET_IDLE_PRIORITY _IOW('b', 6, int)
#define BINDER_SET_CONTEXT_MGR _IOW('b', 7, int)
[// #define BINDER_SET_CONTEXT_MGR _IOW('b', 7, int)
BINDER_SET_CONTEXT_MGR是用于注册Service Manager服务的。
Service Manager是Binder进程间通信机制的核心组件之一,它扮演着Binder进程间通信机制上下文管理者的角色。
Service Manager对应的程序文件为servicemanager,它的源代码位于service_manager.c文件中。
该程序的入口函数main定义如下所示,我们就从main函数开始分析Service Manager的启动过程.
int main(int argc, char **argv)
{
struct binder_state *bs;
[// struct binder_state *bs
结构体binder_state定义在frameworks/base/cmds/servicemanager/binder.c文件中。
具体定义如下:
struct binder_state
{
int fd;
[// int fd
fd保存打开设备文件/dev/binder得到的文件描述符,以便可以通过它来和Binder驱动程序交互。
]// int fd
void *mapped;
[// void *mapped
mapped保存映射的设备文件的地址
]// void *mapped
unsigned mapsize;
[// unsigned mapsize
mapsize保存映射后得到的地址空间大小
]// unsigned mapsize
};
]// struct binder_state *bs
void *svcmgr = BINDER_SERVICE_MANAGER;
[// void *svcmgr = BINDER_SERVICE_MANAGER
宏BINDER_SERVICE_MANAGER的定义如下:
#define BINDER_SERVICE_MANAGER ((void*) 0)
Service Manager是一个特殊的Service组件,它的特殊之处在于与它所对应的Binder本地对象是一个虚拟的对象。这个虚拟的Binder本地对象的地址值等于0,并且在Binder驱动程序中引用了它的Binder引用对象的句柄值也等于0。
]// void *svcmgr = BINDER_SERVICE_MANAGER

bs = binder_open(128*1024);
[// bs = binder_open(128*1024)
调用binder_open函数来打开/dev/binder设备文件
binder_open定义在frameworks/base/cmds/servicemanager/binder.c文件中
struct binder_state *binder_open(unsigned mapsize)
{
struct binder_state *bs;

bs = malloc(sizeof(*bs));
if (!bs) {
errno = ENOMEM;
return 0;
}
[// if (!bs)
上面这段代码是构造了一个binder_state结构体
]// if (!bs)

bs->fd = open("/dev/binder", O_RDWR);
if (bs->fd < 0) {
fprintf(stderr,"binder: cannot open device (%s)\n",
strerror(errno));
goto fail_open;
}
[// if (bs->fd < 0)
上面这段代码打开设备文件/dev/binder
]// if (bs->fd < 0)

bs->mapsize = mapsize;
bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
if (bs->mapped == MAP_FAILED) {
fprintf(stderr,"binder: cannot map device (%s)\n",
strerror(errno));
goto fail_map;
}
[// if (bs->mapped == MAP_FAILED)
上面这段代码将设备文件/dev/binder映射到进程的地址空间
]// if (bs->mapped == MAP_FAILED)

/* TODO: check version */

return bs;

fail_map:
close(bs->fd);
fail_open:
free(bs);
return 0;
}
]// bs = binder_open(128*1024)

if (binder_become_context_manager(bs)) {
ALOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
[// if (binder_become_context_manager(bs))
当打开设备文件/dev/binder文件并且映射进当前进程空间之后,就需要调用binder_become_context_manager来注册成为Binder上下文管理者。
binder_become_context_manager函数的定义如下:
int binder_become_context_manager(struct binder_state *bs)
{
return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}
binder_become_context_manager函数只是ioctl函数来和Binder驱动交互。第三个参数的值为0,用来表示与Service Manager对应的Binder本地对象的地址值。
调用ioctl其实会陷入Binder驱动程序中的binder_ioctl函数中。
]// if (binder_become_context_manager(bs))

svcmgr_handle = svcmgr;
[// svcmgr_handle = svcmgr
svcmgr_handle是个全局变量,定义如下.
void *svcmgr_handle;
]// svcmgr_handle = svcmgr
binder_loop(bs, svcmgr_handler);
[// binder_loop(bs, svcmgr_handler);
当调用binder_become_context_manager函数注册为Service上下文管理者之后,就会调用binder_loop来循环等待Client进程的请求了。
binder_loop的函数定义如下:
void binder_loop(struct binder_state *bs, binder_handler func)
[// void binder_loop(struct binder_state *bs, binder_handler func)
第一个参数bs指向前面在函数binder_open中创建的一个binder_state结构体
第二个参数func是一个函数指针,用来处理Service组件和Client组件的进程间通信请求的,定义在frameworks/base/cmds/servicemanager/service_manager.c文件中,定义如下:
int svcmgr_handler(struct binder_state *bs,
   struct binder_txn *txn,
   struct binder_io *msg,
   struct binder_io *reply)
{
struct svcinfo *si;
uint16_t *s;
unsigned len;
void *ptr;
uint32_t strict_policy;
int allow_isolated;

//    ALOGI("target=%p code=%d pid=%d uid=%d\n",
//         txn->target, txn->code, txn->sender_pid, txn->sender_euid);

if (txn->target != svcmgr_handle)
return -1;

// Equivalent to Parcel::enforceInterface(), reading the RPC
// header with the strict mode policy mask and the interface name.
// Note that we ignore the strict_policy and don't propagate it
// further (since we do no outbound RPCs anyway).
strict_policy = bio_get_uint32(msg);
s = bio_get_string16(msg, &len);
if ((len != (sizeof(svcmgr_id) / 2)) ||
memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
fprintf(stderr,"invalid id %s\n", str8(s));
return -1;
}

switch(txn->code) {
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
s = bio_get_string16(msg, &len);
ptr = do_find_service(bs, s, len, txn->sender_euid);
if (!ptr)
break;
bio_put_ref(reply, ptr);
return 0;

case SVC_MGR_ADD_SERVICE:
s = bio_get_string16(msg, &len);
ptr = bio_get_ref(msg);
[// ptr = bio_get_ref(msg)
这里调用bio_get_ref来得到binder引用对象
void *bio_get_ref(struct binder_io *bio)
{
struct binder_object *obj;

obj = _bio_get_obj(bio);
[// obj = _bio_get_obj(bio)
static struct binder_object *_bio_get_obj(struct binder_io *bio)
{
unsigned n;
unsigned off = bio->data - bio->data0;

/* TODO: be smarter about this? */
for (n = 0; n < bio->offs_avail; n++) {
if (bio->offs[n] == off)
return bio_get(bio, sizeof(struct binder_object));
[// return bio_get(bio, sizeof(struct binder_object))
static void *bio_get(struct binder_io *bio, uint32_t size)
{
size = (size + 3) & (~3);

if (bio->data_avail < size){
bio->data_avail = 0;
bio->flags |= BIO_F_OVERFLOW;
return 0;
}  else {
void *ptr = bio->data;
bio->data += size;
bio->data_avail -= size;
return ptr;
}
}
]// return bio_get(bio, sizeof(struct binder_object))
}

bio->data_avail = 0;
bio->flags |= BIO_F_OVERFLOW;
return 0;
}
]// obj = _bio_get_obj(bio)
if (!obj)
return 0;

if (obj->type == BINDER_TYPE_HANDLE)
return obj->pointer;

return 0;
}
]// ptr = bio_get_ref(msg)
allow_isolated = bio_get_uint32(msg) ? 1 : 0;
if (do_add_service(bs, s, len, ptr, txn->sender_euid, allow_isolated))
return -1;
[// if (do_add_service(bs, s, len, ptr, txn->sender_euid, allow_isolated))
这里调用do_add_service来将Service组件注册到Service Manager中。
int do_add_service(struct binder_state *bs, uint16_t *s, unsigned len, void *ptr, unsigned uid, int allow_isolated)
{
struct svcinfo *si;
//ALOGI("add_service('%s',%p,%s) uid=%d\n", str8(s), ptr,
//        allow_isolated ? "allow_isolated" : "!allow_isolated", uid);

if (!ptr || (len == 0) || (len > 127))
return -1;

if (!svc_can_register(uid, s)) {
ALOGE("add_service('%s',%p) uid=%d - PERMISSION DENIED\n",
str8(s), ptr, uid);
return -1;
}

si = find_svc(s, len);
[// si = find_svc(s, len)
这里调用find_svc来查找是否已经注册过service组件。
struct svcinfo *find_svc(uint16_t *s16, unsigned len)
{
struct svcinfo *si;

for (si = svclist; si; si = si->next) {
if ((len == si->len) &&
!memcmp(s16, si->name, len * sizeof(uint16_t))) {
return si;
}
}
return 0;
}
]// si = find_svc(s, len)
if (si) {
if (si->ptr) {
ALOGE("add_service('%s',%p) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
str8(s), ptr, uid);
svcinfo_death(bs, si);
}
si->ptr = ptr;
} else {
si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
if (!si) {
ALOGE("add_service('%s',%p) uid=%d - OUT OF MEMORY\n",
str8(s), ptr, uid);
return -1;
}
si->ptr = ptr;
si->len = len;
memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
si->name[len] = '\0';
si->death.func = svcinfo_death;
si->death.ptr = si;
si->allow_isolated = allow_isolated;
si->next = svclist;
svclist = si;
}

binder_acquire(bs, ptr);
binder_link_to_death(bs, ptr, &si->death);
return 0;
}
]// if (do_add_service(bs, s, len, ptr, txn->sender_euid, allow_isolated))
break;

case SVC_MGR_LIST_SERVICES: {
unsigned n = bio_get_uint32(msg);

si = svclist;
while ((n-- > 0) && si)
si = si->next;
if (si) {
bio_put_string16(reply, si->name);
return 0;
}
return -1;
}
default:
ALOGE("unknown code %d\n", txn->code);
return -1;
}

bio_put_uint32(reply, 0);
return 0;
}
]// void binder_loop(struct binder_state *bs, binder_handler func)
{
int res;
struct binder_write_read bwr;
unsigned readbuf[32];

bwr.write_size = 0;
bwr.write_consumed = 0;
bwr.write_buffer = 0;

readbuf[0] = BC_ENTER_LOOPER;
binder_write(bs, readbuf, sizeof(unsigned));
[// binder_write(bs, readbuf, sizeof(unsigned))
这里BC_ENTER_LOOPER命令协议表示主动将自己注册为Binder线程。
binder_write的实现如下:
int binder_write(struct binder_state *bs, void *data, unsigned len)
{
struct binder_write_read bwr;
int res;
bwr.write_size = len;
bwr.write_consumed = 0;
bwr.write_buffer = (unsigned) data;
bwr.read_size = 0;
bwr.read_consumed = 0;
bwr.read_buffer = 0;
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
[// res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr)
这里调用ioctl来将当前线程注册到Binder驱动程序中去。这里会陷入到Binder驱动程序中的binder_ioctl函数中去。
]// res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr)
if (res < 0) {
fprintf(stderr,"binder_write: ioctl failed (%s)\n",
strerror(errno));
}
return res;
}
]// binder_write(bs, readbuf, sizeof(unsigned))

for (;;) {
[// for (;;)
binder_loop在一个死循环中处理请求
]// for (;;)
bwr.read_size = sizeof(readbuf);
bwr.read_consumed = 0;
bwr.read_buffer = (unsigned) readbuf;

res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
[// res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr)
这里调用ioctl来将当前线程注册到Binder驱动程序中去。这里会陷入到Binder驱动程序中的binder_ioctl函数中去。
]// res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr)

if (res < 0) {
ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
break;
}

res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func);
[// res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func)
当调用完ioctl与Binder驱动通信数据之后,就会调用binder_parse来处理Binder驱动的返回。
int binder_parse(struct binder_state *bs, struct binder_io *bio, uint32_t *ptr, uint32_t size, binder_handler func)
[// int binder_parse(struct binder_state *bs, struct binder_io *bio, uint32_t *ptr, uint32_t size, binder_handler func)
在binder_parse的参数列表中,
第一个参数是binder_state类型的,表示打开的驱动程序文件
第二个参数是binder_io类型的,表示进程间通信数据,binder_io结构的定义如下:
struct binder_io
{
char *data;            /* pointer to read/write from */
uint32_t *offs;        /* array of offsets */
uint32_t data_avail;   /* bytes available in data buffer */
uint32_t offs_avail;   /* entries available in offsets array */

char *data0;           /* start of data buffer */
uint32_t *offs0;       /* start of offsets buffer */
uint32_t flags;
uint32_t unused;
};
]// int binder_parse(struct binder_state *bs, struct binder_io *bio, uint32_t *ptr, uint32_t size, binder_handler func)
{
int r = 1;
uint32_t *end = ptr + (size / 4);

while (ptr < end) {
uint32_t cmd = *ptr++;
#if TRACE
fprintf(stderr,"%s:\n", cmd_name(cmd));
#endif
switch(cmd) {
case BR_NOOP:
break;
case BR_TRANSACTION_COMPLETE:
break;
case BR_INCREFS:
case BR_ACQUIRE:
case BR_RELEASE:
case BR_DECREFS:
#if TRACE
fprintf(stderr,"  %08x %08x\n", ptr[0], ptr[1]);
#endif
ptr += 2;
break;
case BR_TRANSACTION: {
struct binder_txn *txn = (void *) ptr;
if ((end - ptr) * sizeof(uint32_t) < sizeof(struct binder_txn)) {
ALOGE("parse: txn too small!\n");
return -1;
}
binder_dump_txn(txn);
if (func) {
unsigned rdata[256/4];
struct binder_io msg;
struct binder_io reply;
int res;

bio_init(&reply, rdata, sizeof(rdata), 4);
[// bio_init(&reply, rdata, sizeof(rdata), 4)
这里调用bio_init函数是为了初始化reply
void bio_init(struct binder_io *bio, void *data, uint32_t maxdata, uint32_t maxoffs)
{
uint32_t n = maxoffs * sizeof(uint32_t);

if (n > maxdata) {
bio->flags = BIO_F_OVERFLOW;
bio->data_avail = 0;
bio->offs_avail = 0;
return;
}

bio->data = bio->data0 = (char *) data + n;
bio->offs = bio->offs0 = data;
bio->data_avail = maxdata - n;
bio->offs_avail = maxoffs;
bio->flags = 0;
}
]// bio_init(&reply, rdata, sizeof(rdata), 4)
bio_init_from_txn(&msg, txn);
[// bio_init_from_txn(&msg, txn)
调用bio_init_from_txn是为了初始化msg
void bio_init_from_txn(struct binder_io *bio, struct binder_txn *txn)
{
bio->data = bio->data0 = txn->data;
bio->offs = bio->offs0 = txn->offs;
bio->data_avail = txn->data_size;
bio->offs_avail = txn->offs_size / 4;
bio->flags = BIO_F_SHARED;
}
]// bio_init_from_txn(&msg, txn)
res = func(bs, txn, &msg, &reply);
[// res = func(bs, txn, &msg, &reply)
这里调用func函数来处理请求数据。这个函数指针func指向svcmgr_handler,详细定义参照上面。
]// res = func(bs, txn, &msg, &reply)
binder_send_reply(bs, &reply, txn->data, res);
[// binder_send_reply(bs, &reply, txn->data, res)
这里调用binder_send_reply函数将处理结果返回给Binder驱动程序。
void binder_send_reply(struct binder_state *bs,
   struct binder_io *reply,
   void *buffer_to_free,
   int status)
{
struct {
uint32_t cmd_free;
void *buffer;
uint32_t cmd_reply;
struct binder_txn txn;
} __attribute__((packed)) data;

data.cmd_free = BC_FREE_BUFFER;
data.buffer = buffer_to_free;
data.cmd_reply = BC_REPLY;
data.txn.target = 0;
data.txn.cookie = 0;
data.txn.code = 0;
if (status) {
data.txn.flags = TF_STATUS_CODE;
data.txn.data_size = sizeof(int);
data.txn.offs_size = 0;
data.txn.data = &status;
data.txn.offs = 0;
} else {
data.txn.flags = 0;
data.txn.data_size = reply->data - reply->data0;
data.txn.offs_size = ((char*) reply->offs) - ((char*) reply->offs0);
data.txn.data = reply->data0;
data.txn.offs = reply->offs0;
}
binder_write(bs, &data, sizeof(data));
[// binder_write(bs, &data, sizeof(data))
int binder_write(struct binder_state *bs, void *data, unsigned len)
{
struct binder_write_read bwr;
int res;
bwr.write_size = len;
bwr.write_consumed = 0;
bwr.write_buffer = (unsigned) data;
bwr.read_size = 0;
bwr.read_consumed = 0;
bwr.read_buffer = 0;
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
if (res < 0) {
fprintf(stderr,"binder_write: ioctl failed (%s)\n",
strerror(errno));
}
return res;
}
]// binder_write(bs, &data, sizeof(data))
}
]// binder_send_reply(bs, &reply, txn->data, res)
}
ptr += sizeof(*txn) / sizeof(uint32_t);
break;
}
case BR_REPLY: {
struct binder_txn *txn = (void*) ptr;
if ((end - ptr) * sizeof(uint32_t) < sizeof(struct binder_txn)) {
ALOGE("parse: reply too small!\n");
return -1;
}
binder_dump_txn(txn);
if (bio) {
bio_init_from_txn(bio, txn);
bio = 0;
} else {
/* todo FREE BUFFER */
}
ptr += (sizeof(*txn) / sizeof(uint32_t));
r = 0;
break;
}
case BR_DEAD_BINDER: {
struct binder_death *death = (void*) *ptr++;
death->func(bs, death->ptr);
break;
}
case BR_FAILED_REPLY:
r = -1;
break;
case BR_DEAD_REPLY:
r = -1;
break;
default:
ALOGE("parse: OOPS %d\n", cmd);
return -1;
}
}

return r;
}
]// res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func)
if (res == 0) {
ALOGE("binder_loop: unexpected reply?!\n");
break;
}
if (res < 0) {
ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
break;
}
}
}
]// binder_loop(bs, svcmgr_handler);
return 0;
}
]// #define BINDER_SET_CONTEXT_MGR _IOW('b', 7, int)
#define BINDER_THREAD_EXIT _IOW('b', 8, int)
#define BINDER_VERSION _IOWR('b', 9, struct binder_version)
[// #define BINDER_VERSION _IOWR('b', 9, struct binder_version)
BINDER_VERSION使用一个binder_version结构体与Binder驱动程序交互
struct binder_version {
/* driver protocol version -- increment with incompatible change */
signed long protocol_version;
};
]// #define BINDER_VERSION _IOWR('b', 9, struct binder_version)
]// static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)

猜你喜欢

转载自zzu-007.iteye.com/blog/2261595