
4个模块(进程):client,server,binder驱动,SM组成. 分成java,native,内核层。
java层parcel数据处理,native层bpbinder,bbinder,内核binder驱动binder数据.
使用实例:transact--onTransact :https://www.jianshu.com/p/4ee3fd07da14
aidl: https://www.jianshu.com/p/34326751b2c6
Server: 每个server有一个线程池.一个server有多个service.
Server service:它是binder线程。
binder线程与普通线程的区别是什么呢?
binder线程由binder驱动创建.是一个binder_proc 实体红黑树的一个实体.
实现框架:service binder线程空闲block,等待binder驱动进程唤醒.
当被唤醒,bbinder loop去读取自己mmap 的内存中(binder thread->todo queue)上的数据bc_transaction:target-code-data.& 调用binder->onTransact===>到java onTrantract.onTransact 实现业务逻辑,比如 add(3,5).
将结果传回给bbinder,bbinder写到binder驱动的read buffer&唤醒binder驱动.
程序员只实现上层的onTransact,或者更上层的aidl业务逻辑,不需要care下层的传输.
Client:
talkWithDriver: 通过ioctl与mDriverFD通信,是真正与Binder驱动进行数据读写交互的过程。(binder_write_read结构体用来与Binder设备交换数据的结构).
由于BpBinder中保存了Server在Binder驱动中的Binder引用;因此,IPCThreadState(Bpbinder具体实现类)和Binder驱动通信时,是知道该请求是需要传给哪个Server的。
scenario: client add(3,5); server service实现add
返回理解为add(3,5)返回值,线程计算之后放入binder驱动read buffer。readbuffer放入copy_to_user
notes:binder驱动唤醒service,是唤醒线程还是唤醒进程呢?
看源码是cond-wait 实现唤醒,那么应该是唤醒线程.
两个不同进程的线程怎么能唤醒呢?因为是binder驱动在内核态,所以可以唤醒用户态的线程??(内核态没有进程概念)
binder 一次拷贝原理:
Client(作为数据发送端):ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) 写到binder 驱动内核.binder_ioctl函数使用copy_from_use将从用户空间(Service Manager)传进来的结构体binder_writr_read拷贝进来。
Server service: 用于mmap 读取数据。
scenario: server service 向sm 注册; client 与server通信:1) client 获取SM ref 2) client 与server通信
源码分析:

Client:数据处理parcel-binder数据
AMP.startService:组装flat_binder_object对象等组成的Parcel data;
IPC.writeTransactionData:组装BC_TRANSACTION和binder_transaction_data结构体写入mOut;
IPC.talkWithDriver: 组装BINDER_WRITE_READ和binder_write_read结构体,通过ioctl传输到驱动层。
(talk with driver就是发送给binder driver)
binder 驱动:looper
[3.3]binder_thread_write: 处理binder_write_read.write_buffer数据
[3.4]binder_transaction: 处理write_buffer.binder_transaction_data数据;
创建binder_transaction结构体,记录事务通信的线程来源以及事务链条等相关信息;(不会reply错client)
分配binder_buffer结构体,拷贝当前线程binder_transaction_data的data数据到binder_buffer->data;
notes: 将数据从binder驱动buffer拷贝到target thread buffer.
[3.5]binder_thread_read: 处理binder_transaction结构体数据
组装cmd=BR_TRANSACTION和binder_transaction_data结构体,写入binder_write_read.read_buffer数据
代码说明:binder驱动将client数据write到server service binder thread(binder数据), block在binder_thread_read;当server binder thread将result写到binder驱动buffer。binder驱动读取,然后将result copy_to_user.
binder作为生产者放,server作为消费者读取
Binder 驱动向服务端的 todo 队列里面插入一条事务。
回到server service用户空间
[4.3]IPC.executeCommand:处理BR_TRANSACTION命令, 将binder_transaction_data数据解析成BBinder.transact()所需的参数!!!!!!
[4.7] AMN.onTransact: 层层回调,进入该方法,反序列化数据后,调用server端startService()方法
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
实现:
发起端client线程:向Binder Driver发起binder ioctl请求后, 便采用循环不断talkWithDriver,此时该线程处于阻塞状态, 直到收到如下BR_XXX命令(reply)才会结束该过程.
接收端Server:目标Binder线程创建后, 便进入joinThreadPool()方法, 采用循环不断地循环执行getAndExecuteCommand()方法, 当bwr的读写buffer都没有数据时,则阻塞在binder_thread_read的wait_event过程.
略:Binder主线程的创建是在其所在的进程创建的过程一起创建的,后面再创建的普通binder线程是由spawnPooledThread(false)方法所创建的。
具体实现变量作用:mOut和mIn 分别承担向Binder驱动写数据以及从Binder驱动读数据的功能
- mOut:记录用户空间向Binder Driver写入的命令
- thread→todo: 记录等待当前binder线程需要处理的BINDER_WORK
- mIn: 记录Binder Driver传到用户空间的命令
- 通过waitForResponse()和executeCommand()方法消费BR命令
一个进程一个 ProcessState 对象(具体执行体),一个线程一个IPCThreadState=驱动层一个 Binder_thread 结构体
且每个进程有且只有一个 ProcessState 对象,这是通过单例模式来保证的。
在每个进程中可以有很多个线程,每个线程对应一个 IPCThreadState 对象,在 Binder 驱动层也有与之相对应的结构,那就是 Binder_thread 结构体。
notes: binderservcie不经过sm获取binder.
参见:https://xujiajia.blog.csdn.net/article/details/109906012的最后总结
other:oneway是半程,binder驱动reply.非oneway是全程,等待service reply
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
源码摘要:
getserviceManager都是get bpservicemananger 无论server的add,还是client使用server函数
注意是getservicemanager不是getservice.
注册service:getservicemanager即defaultservicemanager=new Bpbiner
server service ioctl--binder 发送bc_transction(copy_from_user,ipc data handler=0,code is addservice)
注册服务过程就是通过BpBinder来发送ADD_SERVICE_TRANSACTION命令,与实现与binder驱动进行数据交互。
,,,
Java transact-->transactNative-->android_os_BinderProxy_transact-->target->transact(BpBinder::transact)-->IPCThreadState::self()->
transact-->writeTransactionData(传数据)&waitForResponse-->mOut.write(&tr, sizeof(tr));(写入binder_transaction_data数据)
&talkWithDriver+executeCommand-->ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)(//ioctl执行binder读写操作,经过syscall,进入Binder驱动)
addService--writeStrongBinder--android_os_Parcel_writeStrongBinder--JavaBBinderHolder--JavaBBinder
data.writeStrongBinder(service)==parcel->writeStrongBinder(new JavaBBinder(env, obj))
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
下面内容转自:http://gityuan.com/2016/09/04/binder-start-service/,其他http://wangkuiwu.github.io/
源码分析基本流程:流程图(时序图)。类图,每个类介绍。每个文件的每个函数说明,写成step1,2,3....小结流程.
对于所有数据结构统一注释,类的每个变量注释.而且写的都是选过的了,看的更多.
所以源码工作者上面的工作量很多。转载希望能分享给更多人
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
目录
| 0 | Binder系列—开篇 | Binder概述 |
| 1 | Binder系列3—启动Service Manager | ServiceManager守护进程 注册和查询服务 |
| 2 | Binder系列4—获取Service Manager | 获取代理对象BpServiceManager |
| 3 | Binder系列5—注册服务(addService) | 注册Media服务 |
| 4 | Binder系列6—获取服务(getService) | 获取Media代理,以及DeathRecipient |
| 5 | Binder系列7—framework层分析 | framework层服务注册和查询,Binder注册 |
| 6 | 理解Binder线程池的管理 | Binder的startThreadPool过程 |
| 7 | 彻底理解Android Binder通信架构 | startService为主线 |
| 8 | Binder系列10—总结 | Binder的简单总结 |
| 9 | Binder IPC的权限控制 | clearCallingIdentity/restoreCallingIdentity |
| 10 | Binder死亡通知机制之linkToDeath | Binder死亡通知机制 |
Binder使用篇:
| 1 | Binder系列8—如何使用Binder | Native层、Framwrok层自定义Binder服务 |
| 2 | Binder系列9—如何使用AIDL | App层自定义Binder服务 |
正文
一 Binder框架
Binder是进程.通信采用C/S架构. 多client对server结构.分为Bn端(Server)和Bp端(Client).
binder分层:java层,native层
从组件视角来说,包含Client、Server、ServiceManager以及binder驱动,其中ServiceManager用于管理系统中的各种服务。
Binder分层java层和native 层;中间的jni层可以忽略.
架构图如下所示:

图中Client/Server/ServiceManage之间的相互通信都是基于Binder机制。既然基于Binder机制通信,那么同样也是C/S架构,则图中的3大步骤都有相应的Client端与Server端。
- 注册服务(addService):Server进程要先注册Service到ServiceManager。该过程:Server是客户端,ServiceManager是服务端。
- 获取服务(getService):Client进程使用某个Service前,须先向ServiceManager中获取相应的Service。该过程:Client是客户端,ServiceManager是服务端。
- 使用服务:Client根据得到的Service信息建立与Service所在的Server进程通信的通路,然后就可以直接与Service交互。该过程:client是客户端,server是服务端。
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
ServiceManager
Service启动的过程就是向binder驱动注册的过程.
1 流程图

nder
0 init 启动service manager
1 打开驱动 binder_open. 创建全局链表
2 设为守护进程binder_become_context_manager->binder_ioctl->创建binder_node并插入链表
3 binder_looper: 开启for(;;)循环->binder_parse&binder_ioctl->copy_from_user
ServiceManager启动过程主要以下几个阶段:
- 打开binder驱动:binder_open;
- 注册成为binder服务的大管家:binder_become_context_manager;
- 进入无限循环,处理client端发来的请求:binder_loop
ServiceManager最核心的两个功能为查询和注册服务:
- 注册服务:记录服务名和handle信息,保存到svclist列表;
- 查询服务:根据服务名查询相应的的handle信息。
2 启动过程
ServiceManager是由init进程通过解析init.rc文件而创建的
2.1 binder 建立:
主要是驱动设备的初始化(binder_init),打开 (binder_open),映射(binder_mmap),数据操作(binder_ioctl)。

1) main
main()
binder_open()
open("/dev/binder" or "dev/vndbinder")// 打开binder设备
mmap(128 * 1024)// 映射128k大小空间
ioctl(binder_fd, BINDER_SET_CONTEXT_MGR, 0)// 设置binder上下文管理者
// selinux相关设置
...
binder_loop()// 进入主循环
ioctl(binder_fd, BINDER_WRITE_READ, )// 读取请求
binder_parse()// 事件处理
svcmgr_handler()// 处理BR_TRANSACTION事件
do_find_service()// 查找服务
do_add_service()// 注册服务打开binder驱动相关操作:
先调用open()打开binder设备,open()->binder_open(),在Binder驱动层创建一个binder_proc对象,再将binder_proc对象赋值给fd->private_data,同时放入全局链表binder_procs.
调用mmap()进行内存映射,同理mmap()->binder_mmap()方法,该方法会在Binder驱动层创建Binder_buffer对象,并放入当前binder_proc的proc->buffers链表。
3) binder_become_context_manager
binder_become_context_manager-->binder_ioctl-->binder_ioctl_set_ctx_mgr-->binder_new_node
在Binder驱动层创建binder_node结构体对象,并将当前binder_proc加入到binder_node的node->proc。并创建binder_node的async_todo和binder_work两个队列。
4) binder_loop
void binder_loop(struct binder_state *bs, binder_handler func) {
......
readbuf[0] = BC_ENTER_LOOPER;
//将BC_ENTER_LOOPER命令发送给binder驱动,让Service Manager进入循环 【见小节2.4.1】
binder_write(bs, readbuf, sizeof(uint32_t));
for (;;) {
bwr.read_buffer = (uintptr_t) readbuf;
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); //进入循环,不断地binder读写过程
// 解析binder信息 【见小节2.5】
res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
}
}进入循环读写操作,由main()方法传递过来的参数func指向svcmgr_handler。binder_write通过ioctl()将BC_ENTER_LOOPER命令发送给binder驱动,此时bwr只有write_buffer有数据,进入binder_thread_write()方法.
接下来进入for循环,执行ioctl(),此时bwr只有read_buffer有数据,那么进入binder_thread_read()方法
5) binder_parse
int binder_parse(struct binder_state *bs, struct binder_io *bio,
uintptr_t ptr, size_t size, binder_handler func)
{
int r = 1;
uintptr_t end = ptr + (uintptr_t) size;
while (ptr < end) {
uint32_t cmd = *(uint32_t *) ptr;
ptr += sizeof(uint32_t);
switch(cmd) {
case BR_TRANSACTION_COMPLETE:
break;
.......
case BR_TRANSACTION: {
struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
...
if (func) {
bio_init(&reply, rdata, sizeof(rdata), 4);//【见小节2.5.1】
bio_init_from_txn(&msg, txn); //从txn解析出binder_io信息
res = func(bs, txn, &msg, &reply); //【见小节2.6】
binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);//【见小节3.4】
}
ptr += sizeof(*txn);
break;
}
case BR_REPLY: {
struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
...
bio_init_from_txn(bio, txn);
ptr += sizeof(*txn);
r = 0;
break;
}
......
}
}
return r;
}解析binder信息,此处参数ptr指向BC_ENTER_LOOPER,func指向svcmgr_handler。故有请求到来,则调用svcmgr_handler。
6) svcmgr_handler
int svcmgr_handler(struct binder_state *bs,
struct binder_transaction_data *txn,
struct binder_io *msg,
struct binder_io *reply)
{
.....
switch(txn->code) {
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
s = bio_get_string16(msg, &len); //服务名
//根据名称查找相应服务 【见小节3.1】
handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
bio_put_ref(reply, handle);//【见小节3.1.2】
return 0;
case SVC_MGR_ADD_SERVICE:
s = bio_get_string16(msg, &len); //服务名
handle = bio_get_ref(msg); //handle【见小节3.2.3】
do_add_service(bs, s, len, handle, txn->sender_euid,
allow_isolated, txn->sender_pid);//注册指定服务 【见小节3.2】
break;
......
bio_put_uint32(reply, 0);
}核心工作
servicemanager作用是注册服务和查询服务

do_add_service
int do_add_service(struct binder_state *bs,
const uint16_t *s, size_t len,
uint32_t handle, uid_t uid, int allow_isolated,
pid_t spid)
{
struct svcinfo *si;
si = find_svc(s, len);//服务检索【见小节3.1.1】
si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
si->handle = handle;
si->len = len;
memcpy(si->name, s, (len + 1) * sizeof(uint16_t)); //内存拷贝服务信息
......
binder_acquire(bs, handle);//以BC_ACQUIRE命令,handle为目标的信息,通过ioctl发送给binder驱动
//以BC_REQUEST_DEATH_NOTIFICATION命令的信息,通过ioctl发送给binder驱动,主要用于清理内存等收尾工作。[见小节3.3]
......
}binder_ioctl_write_read--copy_from_user--binder_thread_write&bind_thread_read(方向不同)--wake_up_interruptible---copy_to_user
binder_thread_write //举了个例子,分配space放入tolist queue
此方法中的proc, thread都是指当前servicemanager进程的信息. 此时TODO队列有数据,则进入binder_thread_read.
binder_thread_read--putuser
static int binder_thread_read(struct binder_proc *proc,struct binder_thread *thread...)
...
while (1) {
uint32_t cmd;
struct binder_transaction_data tr;
struct binder_work *w;
struct binder_transaction *t = NULL;
switch (w->type) {
case BINDER_WORK_DEAD_BINDER: {
struct binder_ref_death *death;
uint32_t cmd;
death = container_of(w, struct binder_ref_death, work);
if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION)
...
else
cmd = BR_DEAD_BINDER; //进入此分支
put_user(cmd, (uint32_t __user *)ptr);//拷贝到用户空间[见小节3.3.4]
ptr += sizeof(uint32_t);
//此处的cookie是前面传递的svcinfo_death
put_user(death->cookie, (binder_uintptr_t __user *)ptr);
......
}
}
...
return 0;
}将命令BR_DEAD_BINDER写到用户空间, 此处的cookie是前面传递的svcinfo_death. 当binder_loop下一次 执行binder_parse的过程便会处理该消息。
binder_parse--调用回调函数执行体
si->death.func = (void*) svcinfo_death; 可知此处 death->func便是执行svcinfo_death()方法.调用回调函数执行体
binder_send_reply
执行binder_parse方法,先调用svcmgr_handler(),再然后执行binder_send_reply过程。
该方法会调用binder_write进入binder驱动后,将BC_FREE_BUFFER和BC_REPLY命令协议发送给Binder驱动,向client端发送reply.
三 获取ServiceManager
1 概述
获取Service Manager即获取获取BpBinderManager,是通过 defaultServiceManager() 方法来完成.
当进程注册服务(addService)或 获取服务(getService)的过程之前,都需要先调用defaultServiceManager()方法来获取gDefaultServiceManager对象。
对于gDefaultServiceManager对象,如果不存在则创建该对象,创建过程包括调用open()打开binder驱动设备,利用mmap()映射内核的地址空间;如果存在则直接返回;IServiceManager::asInterface() ==defaultServiceManager ==new BpServiceManager(new BpBinder(0))。
BpBinder通过handler来指向所对应BBinder, 在整个Binder系统中handle=0代表ServiceManager所对应的BBinder
2 流程图

四 注册服务(addService)
int main(int argc __unused, char** argv)
{
//获得ProcessState实例对象【见小节2.1】
sp<ProcessState> proc(ProcessState::self());
//获取BpServiceManager对象
sp<IServiceManager> sm = defaultServiceManager();
AudioFlinger::instantiate();
MediaPlayerService::instantiate();//注册多媒体服务
......
//启动Binder线程池
ProcessState::self()->startThreadPool();
//当前线程加入到线程池
IPCThreadState::self()->joinThreadPool();
}本文的重点就是讲解Native层服务注册的过程.
在Native层的服务以media服务为例,来说一说服务注册过程,先来看看media的整个的类关系图

图解:
- 蓝色代表的是注册MediaPlayerService服务所涉及的类
- 绿色代表的是Binder架构中与Binder驱动通信过程中的最为核心的两个类;
- 紫色代表的是注册服务和获取服务的公共接口/父类;
时序图
先通过一幅图来说说,media服务启动过程是如何向servicemanager注册服务的。

aidl->binder.transact-->BpBinder::transact--> IPCThreadState::transact--IPC::transact->BBinder
status_t BpBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);
....
}
IPCThreadState* IPCThreadState::self()
{
....
pthread_key_create(&gTLS, threadDestructor) ! //创建线程的TLS
}
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
// 传输数据 【见小节3.5】
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
...
waitForResponse(&fakeReply);
}
status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{
......
// data为记录Media服务信息的Parcel对象
const status_t err = data.errorCheck();
if (err == NO_ERROR) {
tr.data_size = data.ipcDataSize(); // mDataSize
tr.data.ptr.buffer = data.ipcData(); //mData
tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t); //mObjectsSize
tr.data.ptr.offsets = data.ipcObjects(); //mObjects
}
mOut.writeInt32(cmd); //cmd = BC_TRANSACTION
mOut.write(&tr, sizeof(tr)); //写入binder_transaction_data数据
return NO_ERROR;
}IPCThreadState进行transact事务处理分3部分:
- writeTransactionData() // 传输数据
- waitForResponse() //等待响应
其中handle的值用来标识目的端,注册服务过程的目的端为service manager,此处handle=0所对应的是binder_context_mgr_node对象,正是service manager所对应的binder实体对象。
transact过程,先写完binder_transaction_data数据,接下来执行waitForResponse()方法。
waitForResponse--talkWithDriver()&executeCommand(cmd); ->ioctl
talkWithDriver--数据从mOut到bwr
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
while (1) {
talkWithDriver
mIn.dataAvail()
cmd = mIn.readInt32();
executeCommand(cmd);
}
...
}
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
bwr.write_size = outAvail;
bwr.write_buffer = (uintptr_t)mOut.data();
//接收数据缓冲区信息的填充。如果以后收到数据,就直接填在mIn中了。
bwr.read_size = mIn.dataCapacity();
bwr.read_buffer = (uintptr_t)mIn.data();
//通过ioctl不停的读写操作,跟Binder Driver进行通信
ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)
...
}在waitForResponse过程, 首先执行BR_TRANSACTION_COMPLETE;(binder驱动给client)
另外,目标进程收到事务后,处理BR_TRANSACTION事务。然后发送给当前进程,再执行BR_REPLY命令。(server给client)
binder_write_read结构体用来与Binder设备交换数据的结构(数据传递), 通过ioctl与mDriverFD通信(通信).
真正与Binder驱动进行数据读写交互的过程。 主要是操作mOut和mIn变量。
ioctl()经过系统调用后进入Binder Driver
binder_transaction //创建node,ref,放入list,wake_up都是在这个函数中
static void binder_transaction(struct binder_proc *proc,struct binder_thread *thread...){
struct binder_transaction *t;
struct binder_work *tcomplete;
...
if (tr->target.handle) {
...
} else {
// handle=0则找到servicemanager实体
target_node = binder_context_mgr_node;
}
//target_proc为servicemanager进程
target_proc = target_node->proc;
//找到servicemanager进程的todo队列
target_list = &target_proc->todo;
target_wait = &target_proc->wait;
t = kzalloc(sizeof(*t), GFP_KERNEL);
tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);
//非oneway的通信方式,把当前thread保存到transaction的from字段
if (!reply && !(tr->flags & TF_ONE_WAY))
t->from = thread;
else
t->from = NULL;
t->sender_euid = task_euid(proc->tsk);
t->to_proc = target_proc; //此次通信目标进程为servicemanager进程
t->to_thread = target_thread;
t->code = tr->code; //此次通信code = ADD_SERVICE_TRANSACTION
t->flags = tr->flags; // 此次通信flags = 0
t->priority = task_nice(current);
//从servicemanager进程中分配buffer
t->buffer = binder_alloc_buf(target_proc, tr->data_size,
tr->offsets_size, !reply && (t->flags & TF_ONE_WAY));
......
t->buffer->target_node = target_node;
//分别拷贝用户空间的binder_transaction_data中ptr.buffer和ptr.offsets到内核
copy_from_user(t->buffer->data,
(const void __user *)(uintptr_t)tr->data.ptr.buffer, tr->data_size);
copy_from_user(offp,
(const void __user *)(uintptr_t)tr->data.ptr.offsets, tr->offsets_size);
off_end = (void *)offp + tr->offsets_size;
for (; offp < off_end; offp++) {
struct flat_binder_object *fp;
fp = (struct flat_binder_object *)(t->buffer->data + *offp);
off_min = *offp + sizeof(struct flat_binder_object);
switch (fp->type) {
case BINDER_TYPE_BINDER:
case BINDER_TYPE_WEAK_BINDER: {
struct binder_ref *ref;
struct binder_node *node = binder_get_node(proc, fp->binder);//【见4.3.1】
if (node == NULL) {
//服务所在进程 创建binder_node实体【见4.3.2】
node = binder_new_node(proc, fp->binder, fp->cookie);
...
}
//servicemanager进程binder_ref【见4.3.3】
ref = binder_get_ref_for_node(target_proc, node);
...
//调整type为HANDLE类型
if (fp->type == BINDER_TYPE_BINDER)
fp->type = BINDER_TYPE_HANDLE;
else
fp->type = BINDER_TYPE_WEAK_HANDLE;
binder_inc_ref(ref, fp->type == BINDER_TYPE_HANDLE,
&thread->todo);
} break;
case :...
}
//将BINDER_WORK_TRANSACTION添加到目标队列,本次通信的目标队列为target_proc->todo
t->work.type = BINDER_WORK_TRANSACTION;
list_add_tail(&t->work.entry, target_list);
//将BINDER_WORK_TRANSACTION_COMPLETE添加到当前线程的todo队列
tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
list_add_tail(&tcomplete->entry, &thread->todo);
//唤醒等待队列,本次通信的目标队列为target_proc->wait
if (target_wait)
wake_up_interruptible(target_wait);
return;
}服务注册过程是在服务所在进程创建binder_node,在servicemanager进程创建binder_ref。
binder_send_reply
void binder_send_reply(struct binder_state *bs, struct binder_io *reply, binder_uintptr_t buffer_to_free, int status) {
struct {
uint32_t cmd_free;
binder_uintptr_t buffer;
uint32_t cmd_reply;
struct binder_transaction_data txn;
} __attribute__((packed)) data;
data.cmd_free = BC_FREE_BUFFER; //free buffer命令
data.buffer = buffer_to_free;
data.cmd_reply = BC_REPLY; // reply命令
....
data.txn.data.ptr.buffer = (uintptr_t)reply->data0;
//向Binder驱动通信
binder_write(bs, &data, sizeof(data));
}binder_write进入binder驱动后,将BC_FREE_BUFFER和BC_REPLY命令协议发送给Binder驱动, 向client端发送reply.
总结
服务注册过程(addService)核心功能:在服务所在进程创建binder_node,在servicemanager进程创建binder_ref。
通信流程图如下所示:
过程分析:
- MediaPlayerService进程调用
ioctl()向Binder驱动发送IPC数据,该过程可以理解成一个事务binder_transaction(记为T1),执行当前操作的线程binder_thread(记为thread1)。其中IPC数据内容包含:- Binder协议为BC_TRANSACTION;
- Handle等于0;
- RPC代码为ADD_SERVICE;
- RPC数据为”media.player”。
Binder驱动收到该Binder请求,生成
BR_TRANSACTION命令,选择目标处理该请求的线程,即ServiceManager的binder线程(记为thread2).并将整个binder_transaction数据(记为T2)插入到目标线程的todo队列Service Manager的线程
thread2收到T2后,调用服务注册函数将服务”media.player”注册到服务目录中。当服务注册完成后,生成IPC应答数据(BC_REPLY)- Binder驱动收到该Binder应答请求,生成
BR_REPLY命令,在MediaPlayerService收到该命令后,知道服务注册完成便可以正常使用。
整个过程中,BC_TRANSACTION和BR_TRANSACTION过程是一个完整的事务过程;BC_REPLY和BR_REPLY是一个完整的事务过程。
获取服务(getService) //缺少一个时序图
IPCThreadState::transact: writeTransactionData+waitForResponse
IPC.writeTransactionData:tr.data.ptr.offsets = data.ipcObjects(); //mObjects;mOut.write(&tr, sizeof(tr)); //写入binder_transaction_data数据
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
while (1) {
.......
cmd = mIn.readInt32();
switch (cmd) {
case BR_TRANSACTION_COMPLETE: ...
case BR_DEAD_REPLY: ...
case BR_FAILED_REPLY: ...
case BR_ACQUIRE_RESULT: ...
case BR_REPLY:
{
binder_transaction_data tr;
err = mIn.read(&tr, sizeof(tr));
.....
}
default:
err = executeCommand(cmd);
}
...
return err;
}
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
...
bwr.write_buffer = (uintptr_t)mOut.data();
//接收数据缓冲区信息的填充。如果以后收到数据,就直接填在mIn中了。
bwr.read_size = mIn.dataCapacity();
bwr.read_buffer = (uintptr_t)mIn.data();
//通过ioctl不停的读写操作,跟Binder Driver进行通信【2.8.1】
ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)
}首先向service manager进程发送查询服务的请求(BR_TRANSACTION),当service manager进程收到该命令后,会执行do_find_service() 查询服务所对应的handle.
然后再binder_send_reply()应答发起者,发送BC_REPLY协议,然后调用binder_transaction(),再向服务请求者的Todo队列 插入事务。
接下来,再看看binder_transaction过程//binder_transaction过程非常重要,binder_inc_node or binder_inc_ref &list_add_tail(&tcomplete->entry, &thread->todo);
static void binder_transaction(struct binder_proc *proc,
struct binder_thread *thread,
struct binder_transaction_data *tr, int reply){
//根据各种判定,获取以下信息:
struct binder_thread *target_thread; //目标线程
struct binder_proc *target_proc; //目标进程
struct binder_node *target_node; //目标binder节点
struct list_head *target_list; //目标TODO队列
wait_queue_head_t *target_wait; //目标等待队列
...
//分配两个结构体内存
struct binder_transaction *t = kzalloc(sizeof(*t), GFP_KERNEL);
struct binder_work *tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);
//从target_proc分配一块buffer
t->buffer = binder_alloc_buf(target_proc, tr->data_size,
for (; offp < off_end; offp++) {
switch (fp->type) {
case BINDER_TYPE_BINDER: ...
case BINDER_TYPE_HANDLE: {
struct binder_ref *ref = binder_get_ref(proc, fp->handle,
fp->type == BINDER_TYPE_HANDLE);
...
//此时运行在servicemanager进程,故ref->node是指向服务所在进程的binder实体,
//而target_proc为请求服务所在的进程,此时并不相等。
if (ref->node->proc == target_proc) {
if (fp->type == BINDER_TYPE_HANDLE)
fp->type = BINDER_TYPE_BINDER;
else
fp->type = BINDER_TYPE_WEAK_BINDER;
fp->binder = ref->node->ptr;
fp->cookie = ref->node->cookie; //BBinder服务的地址
binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL);
} else {
struct binder_ref *new_ref;
//请求服务所在进程并非服务所在进程,则为请求服务所在进程创建binder_ref
new_ref = binder_get_ref_for_node(target_proc, ref->node);
fp->binder = 0;
fp->handle = new_ref->desc; //重新赋予handle值
fp->cookie = 0;
binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL);
}
} break;
}
//分别target_list和当前线程TODO队列插入事务
t->work.type = BINDER_WORK_TRANSACTION;
list_add_tail(&t->work.entry, target_list);
tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
list_add_tail(&tcomplete->entry, &thread->todo);
if (target_wait)
wake_up_interruptible(target_wait);
return;
}对于Binder实体,则cookie记录Binder实体的指针;
对于Binder代理,则用handle记录Binder代理的句柄;
framework层分析
如果对Android Binder涉及的类图关系也进行一次分层划分,那么整个Binder从kernel至,Native,JNI,Framework层所涉及的全部类可以使用如下gityuan大神的图归纳总结一下
整个Binder从kernel至,native,JNI,Framework层所涉及的全部类

addService的核心过程:
public void addService(String name, IBinder service, boolean allowIsolated) throws RemoteException {
...
Parcel data = Parcel.obtain(); //此处还需要将java层的Parcel转为Native层的Parcel
// MediaPlayerService对象
data->writeStrongBinder(new JavaBBinder(env, obj));
//remote()指向的是BpBinder对象
BpBinder::transact(ADD_SERVICE_TRANSACTION, *data, reply, 0); //与Binder驱动交互
...
}
注册服务过程就是通过BpBinder来发送ADD_SERVICE_TRANSACTION命令,与实现与binder驱动进行数据交互。
writeStrongBinder-->flatten_binder-->out->writeObject
BpBinder::transact-->IPCThreadState::self()->transact(mHandle, code, data, reply, flags);获取binder thread对象
-->IPCThreadState::transact->writeTransactionData+waitForResponse//传输数据+等待响应
IPCThreadState::writeTransactionData {
tr.target.handle = handle; // handle = 0
tr.code = code; // code = ADD_SERVICE_TRANSACTION
...
mOut.writeInt32(cmd); //cmd = BC_TRANSACTION
mOut.write(&tr, sizeof(tr)); //写入binder_transaction_data数据
}每个线程都有一个IPCThreadState,每个IPCThreadState中都有一个mIn、一个mOut。
mIn 用来接收来自Binder设备的数据,默认大小为256字节;mOut用来存储发往Binder设备的数据,默认大小为256字节。
handle的值用来标识目的端,注册服务过程的目的端为service manager.此处handle=0所对应的是binder_context_mgr_node对象,正是service manager所对应的binder实体对象。
binder_transaction_data结构体是binder驱动通信的数据结构,该过程最终是把Binder请求码BC_TRANSACTION和binder_transaction_data结构体写入到mOut
获取服务
getIServiceManager().getService(name);
class ServiceManagerProxy implements IServiceManager {
public IBinder getService(String name) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IServiceManager.descriptor);
data.writeString(name);
//mRemote为BinderProxy 【见4.3】
mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
//从reply里面解析出获取的IBinder对象【见4.8】
IBinder binder = reply.readStrongBinder();
reply.recycle();
data.recycle();
return binder;
}
}BinderProxy.transact-->transactNative
android_os_BinderProxy_transact //java Parcel转为native Parcel+ new BpBinder(0)对象+//此处便是BpBinder::transact(), 经过native层
static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
jint code, jobject dataObj, jobject replyObj, jint flags)
{
...
//java Parcel转为native Parcel
Parcel* data = parcelForJavaObject(env, dataObj);
Parcel* reply = parcelForJavaObject(env, replyObj);
...
//gBinderProxyOffsets.mObject中保存的是new BpBinder(0)对象
IBinder* target = (IBinder*)
env->GetLongField(obj, gBinderProxyOffsets.mObject);
...
//此处便是BpBinder::transact(), 经过native层[见小节4.5]
status_t err = target->transact(code, *data, reply, flags);
...
return JNI_FALSE;
}
status_t BpBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);// [见小节4.6]
.......
}
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
// 传输数据
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
...
//等待回应事件
err = waitForResponse(reply);
}getService的核心过程:
public static IBinder getService(String name) {
Parcel reply = Parcel.obtain(); //此处还需要将java层的Parcel转为Native层的Parcel
BpBinder::transact(GET_SERVICE_TRANSACTION, *data, reply, 0); //与Binder驱动交互
IBinder binder = javaObjectForIBinder(env, new BpBinder(handle));
...
}
实例:以IWindowManager为例
public interface IWindowManager extends android.os.IInterface {
public static abstract class Stub extends android.os.Binder implements android.view.IWindowManager {
private static final java.lang.String DESCRIPTOR = "android.view.IWindowManager";
public Stub() {
this.attachInterface(this, DESCRIPTOR);
}
public static android.view.IWindowManager asInterface(android.os.IBinder obj) {
......
return new android.view.IWindowManager.Stub.Proxy(obj);
}
public android.os.IBinder asBinder() {
return this;
}
private static class Proxy implements android.view.IWindowManager {
private android.os.IBinder mRemote;
Proxy(android.os.IBinder remote) {
mRemote = remote;
}
public android.os.IBinder asBinder() {
return mRemote;
}
}}....}进程的Binder线程池工作过程
每个进程创建的时候会创建一个线程池.Java层进程的创建都是通过Process.start()方法,向Zygote进程发出创建进程的socket消息,Zygote收到消息后会调用Zygote.forkAndSpecialize()来fork出新进程,在新进程中会调用到RuntimeInit.nativeZygoteInit方法,该方法经过jni映射,最终会调用到app_main.cpp中的onZygoteInit
notes:java层进程创建 Process.start()---socket-->Zygote进程forkAndSpecialize()来fork出新进程--->RuntimeInit.nativeZygoteInit--jni映射-->app_main.cpp中的onZygoteInit
onZygoteInit
virtual void onZygoteInit() {
//获取ProcessState对象
sp<ProcessState> proc = ProcessState::self();
//启动新binder线程 【见小节2.2】
proc->startThreadPool();
}ProcessState::self()是单例模式,主要工作是调用open()打开/dev/binder驱动设备,再利用mmap()映射内核的地址空间,将Binder驱动的fd赋值ProcessState对象中的变量mDriverFD,用于交互操作.
startThreadPool()是创建一个新的binder线程,不断进行talkWithDriver()
PS.startThreadPool
void ProcessState::startThreadPool()
{
.....
spawnPooledThread(true); 【见小节2.3】
}JavaObjectForIBinder作用是创建BinderProxy对象,并将BpBinder对象的地址保存到BinderProxy对象的mObjects中。
获取服务过程就是通过BpBinder来发送GET_SERVICE_TRANSACTION命令,实现与binder驱动进行数据交互。PS.spawnPooledThread:sp t = new PoolThread(isMain);
PoolThread.run:
IPCThreadState::self()->joinThreadPool(mIsMain);
从函数名看起来是创建线程池,其实就只是创建一个线程,该PoolThread继承Thread类。t->run()方法最终调用 PoolThread的threadLoop()方法。
IPC.joinThreadPool
void IPCThreadState::joinThreadPool(bool isMain)
{
result = getAndExecuteCommand(); //处理下一条指令[见小节2.6]
}
status_t IPCThreadState::getAndExecuteCommand()
{
result = talkWithDriver(); //与binder进行交互[见小节2.7]
result = executeCommand(cmd); //执行Binder响应码 [见小节2.8]
}
//mOut有数据,mIn还没有数据。doReceive默认值为true
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
//ioctl执行binder读写操作,经过syscall,进入Binder驱动。调用Binder_ioctl
ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr);
...
}binder_thread_write
处理完BC_ENTER_LOOPER命令后,一般情况下成功设置thread->looper |= BINDER_LOOPER_STATE_ENTERED。那么binder线程的创建是在什么时候呢? 那就当该线程有事务需要处理的时候,进入binder_thread_read()过程
binder_thread_read : put_user(BR_SPAWN_LOOPER...)
binder_thread_read(){
...
//当进程todo队列没有数据,则进入休眠等待状态
ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));
while (1) {
//先考虑从线程todo队列获取事务数据
if (!list_empty(&thread->todo)) {
w = list_first_entry(&thread->todo, struct binder_work, entry);
//线程todo队列没有数据, 则从进程todo对获取事务数据
} else if (!list_empty(&proc->todo) && wait_for_proc_work) {
w = list_first_entry(&proc->todo, struct binder_work, entry);
}
switch (w->type) {
case BINDER_WORK_TRANSACTION: ... break;
case BINDER_WORK_TRANSACTION_COMPLETE:... break;
.....
put_user(cmd, (uint32_t __user *)ptr;
ptr += sizeof(uint32_t);
put_user(death->cookie, (void * __user *)ptr);
ptr += sizeof(void *);
...
break;
}
if (!t)
continue; //只有BINDER_WORK_TRANSACTION命令才能继续往下执行
...
break;
}
done:
*consumed = ptr - buffer;
// 生成BR_SPAWN_LOOPER命令,用于创建新的线程
put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer);
......
return 0;
}从system_server的binder线程一直的执行流:
IPC.joinThreadPool –> IPC.getAndExecuteCommand() -> IPC.talkWithDriver()-->IPC.executeCommand()
-->//创建新的binder线程: mProcess->spawnPooledThread(false);
status_t IPCThreadState::executeCommand(int32_t cmd)
{
status_t result = NO_ERROR;
switch ((uint32_t)cmd) {
...
case BR_SPAWN_LOOPER:
//创建新的binder线程 【见小节2.3】
mProcess->spawnPooledThread(false);
break;
...
}
return result;
}Binder主线程的创建是在其所在进程创建的过程一起创建的,后面再创建的普通binder线程是由spawnPooledThread(false)方法所创建的
总结
Binder设计架构中,只有第一个Binder主线程(也就是Binder_1线程)是由应用程序主动创建,Binder线程池的普通线程都是由Binder驱动根据IPC通信需求创建,Binder线程的创建流程图:

每次由Zygote fork出新进程的过程中,伴随着创建binder线程池,调用spawnPooledThread来创建binder主线程。
当线程执行binder_thread_read的过程中,发现当前没有空闲线程,没有请求创建线程,且没有达到上限,则创建新的binder线程。
Android Binder通信架构
AMP和AMN都是实现了IActivityManager接口,AMS继承于AMN.
其中AMP作为Binder的客户端,运行在各个app所在进程, AMN(或AMS)运行在系统进程system_server
可以看出无论是注册服务和获取服务的过程都需要ServiceManager,需要注意的是此处的Service Manager是指Native层的ServiceManager(C++),并非指framework层的ServiceManager(Java)。
通信过程
startService
public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType, String callingPackage, int userId) throws RemoteException {
//获取或创建Parcel对象【见小节2.2】
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
service.writeToParcel(data, 0);
//写入Parcel数据 【见小节2.3】
data.writeString(resolvedType);
data.writeString(callingPackage);
data.writeInt(userId);
//通过Binder传递数据【见小节2.5】
mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
//根据reply数据来创建ComponentName对象
ComponentName res = ComponentName.readFromParcel(reply);
return res;
}主要功能:
- 获取或创建两个Parcel对象,data用于发送数据,reply用于接收应答数据.
- 将startService相关数据都封装到Parcel对象data, 其中descriptor = “android.app.IActivityManager”;
- 通过Binder传递数据,并将应答消息写入reply;
- 读取reply应答消息的异常情况和组件对象;
nativeCreate这是native方法,经过JNI进入native层, 调用android_os_Parcel_create()方法.
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
//获取名为"activity"的服务
IBinder b = ServiceManager.getService("activity");
//创建AMP对象[见流程2.4.4]
IActivityManager am = asInterface(b);
return am;
}
};
可知ServiceManager.getService(“activity”)返回的是指向目标服务AMS的代理对象BinderProxy对象,由该代理对象可以找到目标服务AMS所在进程
AMN.asInterface
public abstract class ActivityManagerNative extends Binder implements IActivityManager {
static public IActivityManager asInterface(IBinder obj) {
IActivityManager in = (IActivityManager)obj.queryLocalInterface(descriptor);
//[见流程2.4.6]
return new ActivityManagerProxy(obj);
}
...
}
此时obj为BinderProxy对象, 记录着远程进程system_server中AMS服务的binder线程的handle.
对于Binder IPC的过程中, asInterface()方法对于不同进程的调用则会是远程代理对象BinderProxy.
创建AMP
Java transact-->transactNative-->android_os_BinderProxy_transact-->target->transact(BpBinder::transact)-->IPCThreadState::self()->
transact-->writeTransactionData(传数据)&waitForResponse-->mOut.write(&tr, sizeof(tr));(写入binder_transaction_data数据)
&talkWithDriver+executeCommand-->ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)(//ioctl执行binder读写操作,经过syscall,进入Binder驱动)
Binder driver //将proc加入list
binder_ioctl-->thread = binder_get_thread(proc)+binder_ioctl_write_read
static int binder_ioctl_write_read(struct file *filp,
unsigned int cmd, unsigned long arg,
struct binder_thread *thread)
{
struct binder_write_read bwr;
//将用户空间bwr结构体拷贝到内核空间
copy_from_user(&bwr, ubuf, sizeof(bwr));
//将数据放入目标进程【见小节3.3】
ret = binder_thread_write(proc, thread,
bwr.write_buffer,
bwr.write_size,
&bwr.write_consumed);
//读取自己队列的数据 【见小节3.5】
ret = binder_thread_read(proc, thread, bwr.read_buffer,
bwr.read_size,
&bwr.read_consumed,
filp->f_flags & O_NONBLOCK);
//当进程的todo队列有数据,则唤醒在该队列等待的进程
if (!list_empty(&proc->todo))
wake_up_interruptible(&proc->wait);
copy_to_user(ubuf, &bwr, sizeof(bwr));
}
此时arg是一个binder_write_read结构体,mOut数据保存在write_buffer,所以write_size>0,
但此时read_size=0。首先,将用户空间bwr结构体拷贝到内核空间,然后执行binder_thread_write()操作.
/
static int binder_thread_write(struct binder_proc *proc,
struct binder_thread *thread,
binder_uintptr_t binder_buffer, size_t size,
binder_size_t *consumed)
{
uint32_t cmd;
void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
void __user *ptr = buffer + *consumed;
void __user *end = buffer + size;
while (ptr < end && thread->return_error == BR_OK) {
//拷贝用户空间的cmd命令,此时为BC_TRANSACTION
if (get_user(cmd, (uint32_t __user *)ptr)) -EFAULT;
ptr += sizeof(uint32_t);
switch (cmd) {
case BC_TRANSACTION:
case BC_REPLY: {
struct binder_transaction_data tr;
//拷贝用户空间的binder_transaction_data
copy_from_user(&tr, ptr, sizeof(tr));
ptr += sizeof(tr);
binder_transaction(proc, thread, &tr, cmd == BC_REPLY);// 见小节3.4】
break;
}
...
}
*consumed = ptr - buffer;
}
return 0;
}
不断从binder_buffer所指向的地址获取cmd, 当只有BC_TRANSACTION或者BC_REPLY时, 则调用binder_transaction()来处理事务.
static void binder_transaction(struct binder_proc *proc,
struct binder_thread *thread,
struct binder_transaction_data *tr, int reply){
......
if (tr->target.handle) {
struct binder_ref *ref;
// 由handle 找到相应 binder_ref, 由binder_ref 找到相应 binder_node
ref = binder_get_ref(proc, tr->target.handle);
target_node = ref->node;
} else {
target_node = binder_context_mgr_node;
}
// 由binder_node 找到相应 binder_proc
target_proc = target_node->proc;
t = kzalloc(sizeof(*t), GFP_KERNEL);
tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);
t->to_proc = target_proc; //此次通信目标进程为system_server
t->to_thread = target_thread;
t->code = tr->code; //此次通信code = START_SERVICE_TRANSACTION
....
//从目标进程target_proc中分配内存空间【3.4.1】
t->buffer = binder_alloc_buf(target_proc, tr->data_size,
tr->offsets_size, !reply && (t->flags & TF_ONE_WAY));
.....
if (target_node)
binder_inc_node(target_node, 1, 0, NULL); //引用计数加1
//分别拷贝用户空间的binder_transaction_data中ptr.buffer和ptr.offsets到目标进程的binder_buffer
copy_from_user(t->buffer->data,
(const void __user *)(uintptr_t)tr->data.ptr.buffer, tr->data_size);
copy_from_user(offp,
(const void __user *)(uintptr_t)tr->data.ptr.offsets, tr->offsets_size);
.....
for (; offp < off_end; offp++) {
....
switch (fp->type) {
...
case BINDER_TYPE_HANDLE:
case BINDER_TYPE_WEAK_HANDLE: {
//处理引用计数情况
struct binder_ref *ref = binder_get_ref(proc, fp->handle);
if (ref->node->proc == target_proc) {
....
binder_inc_node(ref->node, fp->type == BINDER_TYPE_BINDER, 0, NULL);
} else {
....
binder_inc_ref(new_ref, fp->type == BINDER_TYPE_HANDLE, NULL);
}
} break;
...
}
}
if (reply) {
//BC_REPLY的过程
binder_pop_transaction(target_thread, in_reply_to);
}...
else {
//BC_TRANSACTION 且 oneway,则加入异步todo队列
if (target_node->has_async_transaction) {
target_list = &target_node->async_todo;
target_wait = NULL;
} else
target_node->has_async_transaction = 1;
}
//将BINDER_WORK_TRANSACTION添加到目标队列,即target_proc->todo
t->work.type = BINDER_WORK_TRANSACTION;
list_add_tail(&t->work.entry, target_list);
//将BINDER_WORK_TRANSACTION_COMPLETE添加到当前线程队列,即thread->todo
tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
list_add_tail(&tcomplete->entry, &thread->todo);
//唤醒等待队列,本次通信的目标队列为target_proc->wait
if (target_wait)
wake_up_interruptible(target_wait);
return;
}主要功能:
- 查询目标进程的过程: handle -> binder_ref -> binder_node -> binder_proc
- 将
BINDER_WORK_TRANSACTION添加到目标队列target_list:- call事务, 则目标队列target_list=
target_proc->todo; - reply事务,则目标队列target_list=
target_thread->todo; - async事务,则目标队列target_list=
target_node->async_todo.
- call事务, 则目标队列target_list=
- 数据拷贝
- 将用户空间binder_transaction_data中ptr.buffer和ptr.offsets拷贝到目标进程的binder_buffer->data;
- 这就是只拷贝一次的真理所在;
- 设置事务栈信息
- BC_TRANSACTION且非oneway, 则将当前事务添加到thread->transaction_stack;
- 事务分发过程:
- 将
BINDER_WORK_TRANSACTION添加到目标队列(此时为target_proc->todo队列); - 将
BINDER_WORK_TRANSACTION_COMPLETE添加到当前线程thread->todo队列;
- 将
- 唤醒目标进程target_proc开始执行事务。
该方法中proc/thread是指当前发起方的进程信息,而binder_proc是指目标接收端进程。 此时当前线程thread的todo队列已经有事务, 接下来便会进入binder_thread_read来处理相关的事务
binder_ioctl_write_read
//当进程todo队列没有数据,则进入休眠等待状态
ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));
copy_from_user(将用户空间bwr结构体拷贝到内核空间)--binder_thread_write--binder_thread_read+wake_up_interruptible
--copy_to_user
binder_thread_write:get_user--copy_from_user(拷贝用户空间的binder_transaction_data)--binder_transaction
--binder_transaction:kzalloc--copy_from_user--binder_pop_transaction/target_list(添加到目标队列)--wake_up_interruptible(唤醒等待队列)
binder_alloc_buf:binder_update_page_range//分配物理页
binder_thread_read:
--wait_event_freezable_exclusive/wait_event_freezable( //当线程todo队列有数据则执行往下执行;当线程todo队列没有数据,则进入休眠等待状态)
list_first_entry(&thread->todo,...)--list_first_entry(&proc->todo,...)
cmd = BR_TRANSACTION; //设置命令为BR_TRANSACTION or cmd = BR_REPLY; //设置命令为BR_REPLY
//将cmd和数据写回用户空间
put_user(cmd, (uint32_t __user *)ptr)
// 生成BR_SPAWN_LOOPER命令,用于创建新的线程
put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer);
此处wait_for_proc_work是指当前线程todo队列为空,并且transaction_stack也为空,该值为true.将相应的cmd和数据写回用户空间:
当wait_for_proc_work = false, 则进入线程的等待队列thread->wait, 直到thread->todo队列有事务才往下执行;
获取并处理thread->todo队列中的事务;将相应的cmd和数据写回用户空间.
当wait_for_proc_work = true, 则进入线程的等待队列proc->wait, 直到proc->todo队列有事务才往下执行;
获取并处理proc->todo队列中的事务;将相应的cmd和数据写回用户空间.
下一步何去何从
执行完binder_thread_write方法后, 通过binder_transaction()首先写入BINDER_WORK_TRANSACTION_COMPLETE写入当前线程.
这时bwr.read_size > 0, 回到binder_ioctl_write_read方法, 便开始执行binder_thread_read();
在binder_thread_read()方法, 将获取cmd=BR_TRANSACTION_COMPLETE, 再将cmd和数据写回用户空间;
一次Binder_ioctl完成,接着回调用户空间方法talkWithDriver(),刚才的数据以写入mIn.
这时mIn有可读数据,回到IPC.waitForResponse()方法,完成BR_TRANSACTION_COMPLETE过程.
如果本次transaction采用非oneway方式, 这次Binder通信便完成, 否则还是要等待Binder服务端的返回。
对于startService过程, 采用的便是非oneway方式,那么发起者进程还会继续停留在waitForResponse()方法,继续talkWithDriver(),然后休眠在binder_thread_read()的wait_event_freezable()过程,等待当前线程的todo队列有数据的到来,即等待收到BR_REPLY消息.
由于在前面binder_transaction()除了向自己所在线程写入了BINDER_WORK_TRANSACTION_COMPLETE, 还向目标进程(此处为system_server)写入了BINDER_WORK_TRANSACTION命令,那么接下里介绍system_server进程的工作
回到用户空间
system_server的binder线程是如何运转的(server service都在system_server中),那么就需要从Binder线程的创建开始说起, Binder线程的创建有两种方式:
- ProcessState::self()->startThreadPool();
- IPCThreadState::self()->joinThreadPool();
调用链如下: startThreadPool()过程会创建新Binder线程,再经过层层调用也会进入joinThreadPool()方法.system_server的binder线程从IPC.joinThreadPool –>IPC.getAndExecuteComman -> IPC.talkWithDriver() ->IPC.executeCommand()方法
接下来从joinThreadPool说起:IPCThreadState::executeCommand-->mIn.read&BBinder->transact&sendReply(reply, 0);
void IPCThreadState::joinThreadPool(bool isMain)
{
......
do {
result = getAndExecuteCommand();//获取并执行命令【见小节4.2】
} while (result != -ECONNREFUSED && result != -EBADF);
}
status_t IPCThreadState::getAndExecuteCommand()
{
result = talkWithDriver(); //该Binder Driver进行交互
if (result >= NO_ERROR) {
size_t IN = mIn.dataAvail();
cmd = mIn.readInt32(); //读取命令
result = executeCommand(cmd); //【见小节4.3】
......
}
}此时system_server的binder线程空闲停在binder_thread_read()方法来处理进程/线程新的事务.
由【小节3.4】可知收到的是BINDER_WORK_TRANSACTION命令, 再经过Binder_thread_read()后生成命令cmd=BR_TRANSACTION.再将cmd和数据写回用户空间(反射从c++调用java)
status_t IPCThreadState::executeCommand(int32_t cmd)
{ .......
switch ((uint32_t)cmd) {
case BR_TRANSACTION:
{
binder_transaction_data tr;
result = mIn.read(&tr, sizeof(tr)); //读取mIn数据
Parcel reply;
// tr.cookie里存放的是BBinder子类JavaBBinder [见流程4.4]
error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,
&reply, tr.flags);
sendReply(reply, 0);
}
break;
}}
status_t BBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{ .......
err = onTransact(code, data, reply, flags); //见流程4.5
}
virtual status_t onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0)
{
JNIEnv* env = javavm_to_jnienv(mVM);
IPCThreadState* thread_state = IPCThreadState::self();
//调用Binder.execTransact [见流程4.6]// 反射从c++调用java
jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);
}还记得AndroidRuntime::startReg过程吗, 其中有一个过程便是register_android_os_Binder(),该过程会把gBinderOffsets.mExecTransact便是Binder.java中的execTransact()方法.
另外,此处mObject是在服务注册addService过程,会调用writeStrongBinder方法, 将Binder对象传入了JavaBBinder构造函数的参数, 最终赋值给mObject. 在本次通信过程中Object为ActivityManagerNative对象.
从C++代码回到了Java代码. 进入AMN.execTransact, 由于AMN继续于Binder对象, 接下来进入Binder.execTransact
下面是java层调用
private boolean execTransact(int code, long dataObj, long replyObj, int flags) {
Parcel data = Parcel.obtain(dataObj);
Parcel reply = Parcel.obtain(replyObj);
// 调用子类AMN.onTransact方法 [见流程4.7]
res = onTransact(code, data, reply, flags);
}
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
switch (code) {
...
case START_SERVICE_TRANSACTION: {
IBinder b = data.readStrongBinder();
//生成ApplicationThreadNative的代理对象,即ApplicationThreadProxy对象
IApplicationThread app = ApplicationThreadNative.asInterface(b);
Intent service = Intent.CREATOR.createFromParcel(data);
......
//调用ActivityManagerService的startService()方法【见流程4.8】
ComponentName cn = startService(app, service, resolvedType, callingPackage, userId);
ComponentName.writeToParcel(cn, reply);
return true;
}
}
public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType, String callingPackage, int userId) throws TransactionTooLargeException {
synchronized(this) {
...
ComponentName res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid, callingPackage, userId);
}
}Reply流程
status_t IPCThreadState::sendReply(const Parcel& reply, uint32_t flags)
{
err = writeTransactionData(BC_REPLY, flags, -1, 0, reply, &statusBuffer);
return waitForResponse(NULL, NULL);
}同理经过IPC.talkWithDriver -> binder_ioctl -> binder_ioctl_write_read -> binder_thread_write->binder_transaction方法
// reply =true
static void binder_transaction(struct binder_proc *proc,
struct binder_thread *thread,
struct binder_transaction_data *tr, int reply)
{
...
if (reply) {
in_reply_to = thread->transaction_stack; //接收端的事务栈
...
thread->transaction_stack = in_reply_to->to_parent;
target_thread = in_reply_to->from; //发起端的线程
target_proc = target_thread->proc; //发起端的进程
}
if (target_thread) {
//发起端的线程
target_list = &target_thread->todo;
target_wait = &target_thread->wait;
}
t = kzalloc(sizeof(*t), GFP_KERNEL);
tcomplete = kzalloc(sizeof(*tcomplete), GFP_KERNEL);
...
if (!reply && !(tr->flags & TF_ONE_WAY))
t->from = thread;
else
t->from = NULL; //进入该分支
t->sender_euid = task_euid(proc->tsk);
t->to_proc = target_proc;
t->to_thread = target_thread;
.....
// 发起端进程分配buffer
t->buffer = binder_alloc_buf(target_proc, tr->data_size,
tr->offsets_size, !reply && (t->flags & TF_ONE_WAY));
...
t->buffer->allow_user_free = 0;
t->buffer->transaction = t;
t->buffer->target_node = target_node;
if (target_node)
binder_inc_node(target_node, 1, 0, NULL);
//分别拷贝用户空间的binder_transaction_data中ptr.buffer和ptr.offsets到内核
copy_from_user(t->buffer->data,
(const void __user *)(uintptr_t)tr->data.ptr.buffer, tr->data_size);
copy_from_user(offp,
(const void __user *)(uintptr_t)tr->data.ptr.offsets, tr->offsets_size);
...
if (reply) {
binder_pop_transaction(target_thread, in_reply_to);
}
//将BINDER_WORK_TRANSACTION添加到目标队列,本次通信的目标队列为target_thread->todo
t->work.type = BINDER_WORK_TRANSACTION;
list_add_tail(&t->work.entry, target_list);
//将BINDER_WORK_TRANSACTION_COMPLETE添加到当前线程的todo队列
tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
list_add_tail(&tcomplete->entry, &thread->todo);
//唤醒等待队列,本次通信的目标队列为target_thread->wait
if (target_wait)
wake_up_interruptible(target_wait);
return;binder_transaction -> binder_thread_read -> IPC.waitForResponse,收到BR_REPLY来回收buffer.
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
while (1) {
err=talkWithDriver();
cmd = mIn.readInt32();
switch (cmd) {
...
case BR_REPLY:
{
binder_transaction_data tr;
err = mIn.read(&tr, sizeof(tr));
}
default:
err = executeCommand(cmd);
...
break;
}...}}
binder_thread_read(){
...
while (1) {
//从线程todo队列获取事务数据
if (!list_empty(&thread->todo)) {
w = list_first_entry(&thread->todo, struct binder_work, entry);
}
switch (w->type) {
case BINDER_WORK_TRANSACTION:
//获取transaction数据
t = container_of(w, struct binder_transaction, work);
break;
...
}
...
if (t->buffer->target_node) {
//获取目标node
struct binder_node *target_node = t->buffer->target_node;
...
cmd = BR_TRANSACTION; //设置命令为BR_TRANSACTION
}
...
//将cmd和数据写回用户空间
if (put_user(cmd, (uint32_t __user *)ptr)) return -EFAULT;
ptr += sizeof(uint32_t);
if (copy_to_user(ptr, &tr, sizeof(tr))) return -EFAULT;
ptr += sizeof(tr);
......}}通信流程

- 发起端线程向Binder Driver发起binder ioctl请求后, 便采用环不断talkWithDriver,此时该线程处于阻塞状态, 直到收到如下BR_XXX命令才会结束该过程
- 左图中waitForResponse收到BR_TRANSACTION_COMPLETE,则直接退出循环, 则没有机会执行executeCommand()方法, 故将其颜色画为灰色. 除以上5种BR_XXX命令, 当收到其他BR命令,则都会执行executeCommand过程.
- 目标Binder线程创建后, 便进入joinThreadPool()方法, 采用循环不断地循环执行getAndExecuteCommand()方法, 当bwr的读写buffer都没有数据时,则阻塞在binder_thread_read的wait_event过程.另外,正常情况下binder线程一旦创建则不会退出.
通信协议
从通信协议的角度来看这个过程:

- Binder客户端或者服务端向Binder Driver发送的命令都是以BC_开头,例如本文的
BC_TRANSACTION和BC_REPLY, 所有Binder Driver向Binder客户端或者服务端发送的命令则都是以BR_开头, 例如本文中的BR_TRANSACTION和BR_REPLY. - 只有当
BC_TRANSACTION或者BC_REPLY时, 才调用binder_transaction()来处理事务. 并且都会回应调用者一个BINDER_WORK_TRANSACTION_COMPLETE事务, 经过binder_thread_read()会转变成BR_TRANSACTION_COMPLETE. - startService过程便是一个非oneway的过程, 那么oneway的通信过程如下所述.
说一说oneway
上图是非oneway通信过程的协议图, 下图则是对于oneway场景下的通信协议图:

当收到BR_TRANSACTION_COMPLETE则程序返回,有人可能觉得好奇,为何oneway怎么还要等待回应消息? 我举个例子,你就明白了.
数据流

- AMP.startService:组装flat_binder_object对象等组成的Parcel data;
- IPC.writeTransactionData:组装BC_TRANSACTION和binder_transaction_data结构体,写入mOut;
- IPC.talkWithDriver: 组装BINDER_WRITE_READ和binder_write_read结构体,通过ioctl传输到驱动层。
进入驱动后
- [3.3]binder_thread_write: 处理binder_write_read.write_buffer数据
- [3.4]binder_transaction: 处理write_buffer.binder_transaction_data数据;
- 创建binder_transaction结构体,记录事务通信的线程来源以及事务链条等相关信息;
- 分配binder_buffer结构体,拷贝当前线程binder_transaction_data的data数据到binder_buffer->data;
- [3.5]binder_thread_read: 处理binder_transaction结构体数据
- 组装cmd=BR_TRANSACTION和binder_transaction_data结构体,写入binder_write_read.read_buffer数据
回到用户空间
- [4.3]IPC.executeCommand:处理BR_TRANSACTION命令, 将binder_transaction_data数据解析成BBinder.transact()所需的参数
- [4.7] AMN.onTransact: 层层回调,进入该方法,反序列化数据后,调用startService()方法
client transcation---bpnative transcation--- bbnative transcation
每个server一个ProcessState对象,每个server有一个线程池,server中每个service一个线程,每个线程对应一个IPCThreadState对象
每个server对应一个binder_proc结构体,其变量rb_root threads管理所有线程。
Binder传输过程
对于多个不同进程向同一个进程发送事务时,这个同一个进程或线程的事务需要串行执行,在Binder驱动中为binder_proc和binder_thread都有todo队列,
在Binder驱动中为binder_proc和binder_thread都有todo队列。
对于进程间的通信,就是发送端把binder_transaction节点,插入到目标进程或其子线程的todo队列中,等目标进程或线程不断循环地从todo队列中取出数据并进行相应的操作
在Binder驱动层,每个接收端进程都有一个todo队列,用于保存发送端进程发送过来的binder请求,
这类请求可以由接收端进程的任意一个空闲的binder线程处理;
接收端进程存在一个或多个binder线程,在每个binder线程里都有一个todo队列,也是用于保存发送端进程发送过来的binder请求,这类请求只能由当前binder线程来处理。
binder线程在空闲时进入可中断的休眠状态,当自己的todo队列或所属进程的todo队列有新的请求到来时便会唤醒,
如果是由所需进程唤醒的,那么进程会让其中一个线程处理响应的请求,其他线程再次进入休眠状态
Binder路由
先来看看Native Binder IPC的两个重量级对象:BpBinder(客户端)和BBinder(服务端)都是Android中Binder通信相关的代表,它们都从IBinder类中派生而来,关系图如下:
binder的路由原理:BpBinder发送端,根据handler,在当前binder_proc中,找到相应的binder_ref,由binder_ref再找到目标binder_node实体,由目标binder_node再找到目标进程binder_proc。简单地方式是直接把binder_transaction节点插入到binder_proc的todo队列中,完成传输过程。
小结:
BpBinder(客户端)和BBinder(服务端)是两个对象.不是两个线程
进程之间数据传输:
BpBinder发送端,根据handler,在当前binder_proc中,找到相应的binder_ref,由binder_ref再找到目标binder_node实体,由目标binder_node再找到目标进程binder_proc。
简单地方式是直接把binder_transaction节点插入到binder_proc的binder thread的todo队列中,完成传输过程
源码分析:
binder_thread_write
while(1) {
get_user(cmd, (uint32_t __user *)ptr);
switch (cmd) {
get_user(target, (uint32_t __user *)ptr); //获取target
ref = binder_get_ref(proc, target); //拿到目标服务的binder_ref
list_add_tail(&death->work.entry, &proc->todo);
wake_up_interruptible(&proc->wait);
}
binder_thread_read:
//唤醒等待中的binder线程 ; binder_has_proc_work是target进程
wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread));
while(1) {//遍历target 进程
//从todo队列拿出前面放入的binder_work, 此时type为BINDER_WORK_DEAD_BINDER
if (!list_empty(&thread->todo)) {
w = list_first_entry(&thread->todo, struct binder_work,
entry);
} else if (!list_empty(&proc->todo) && wait_for_proc_work) {
w = list_first_entry(&proc->todo, struct binder_work,
entry);
}
switch(type ){
case type:
put_user拷贝到用户空间
IPC.executeCommand {
BpBinder *proxy = (BpBinder*)mIn.readPointer();
mOut.writePointer((uintptr_t)proxy);
},,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
2.6 Android Java层Binder框架的初始化小结

一. Native Binder架构解析

- 在正式开始进行源码分析前,先看下Native Binder服务注册整体示意图:


消息流程
2.1 Binder设计
2.1.1 内核空间的Binder设计
红黑树:
binder_proc是描述进程上下文信息的,每一个用户空间的进程都对应一个binder_proc结构体。
binder_node是Binder实体对应的结构体,它是Server在Binder驱动中的体现。
binder_ref是Binder引用对应的结构体,它是Client在Binder驱动中的体现。
如上图所示,binder_proc中包含了3棵红黑树

1. Binder实体
Binder实体,是各个Server以及ServiceManager在内核中的存在形式。
Binder实体实际上是内核中binder_node结构体的对象,它的作用是在内核中保存Server和ServiceManager的信息(例如,Binder实体中保存了Server对象在用户空间的地址)。
简言之,Binder实体是Server在Binder驱动中的存在形式,内核通过Binder实体可以找到用户空间的Server对象。
2. Binder引用
所谓Binder引用,实际上是内核中binder_ref结构体的对象,它的作用是在表示"Binder实体"的引用.
换句话说,每一个Binder引用都是某一个Binder实体的引用,通过Binder引用可以在内核中找到它对应的Binder实体。
Client要和Server通信,它就是通过保存一个Server对象的Binder引用,再通过该Binder引用在内核中找到对应的Binder实体,进而找到Server对象,然后将通信内容发送给Server对象。
Binder实体和Binder引用都是内核(即Binder驱动)中的数据结构。
每一个Server在内核中就表现为一个Binder实体,而每一个Client则表现为一个Binder引用。
这样,每个Binder引用都对应一个Binder实体,而每个Binder实体则可以多个Binder引用。
Server注册到ServiceManager中: Binder驱动会创建Server对应的Binder实体,并在ServiceManager的红黑树中添加该Binder实体的Binder引用。
Client获取远程服务: Client发送的请求数据中,会包括它要获取的Server的服务名;而ServiceManager正是根据这个服务名来找到Server的。ServiceManager通过Binder驱动将Server对应的Binder实体的Binder引用信息。而Client根据该Binder引用信息创建一个Server对应的远程服务。这个远程服务就是Server的代理,Client通过调用该远程服务的接口,就相当于在调用Server的服务接口一样。
2.1.2 用户空间的Binder设计
上面是用户空间中Binder模型图
例如,对于MediaPlayerService服务而言,本地服务就是MediaPlayerService自身,远程服务是BpMediaPlayerService,而服务接口是IMediaPlayerService。
当Client需要向MediaPlayerService发送请求时,它需要先获取到服务的代理(即,远程服务对象),也就是BpMediaPlayerService实例,然后通过该实例和MediaPlayerService进行通信。
(03) a) 当Client获取到远程服务对象之后,它就可以和Server进行通信了。
当它需要向Server发送请求时,它会调用远程服务接口;远程服务能够获取到BpBinder对象,而BpBinder则通过IPCThreadState和Binder驱动进行通信。
由于BpBinder中保存了Server在Binder驱动中的Binder引用;因此,IPCThreadState和Binder驱动通信时,是知道该请求是需要传给哪个Server的。
Binder驱动通过Binder引用找到对应的Binder实体,然后将Binder实体中保存的"Server对应的本地服务对象的地址"返回给用户空间。
b) 当IPC收到Binder驱动反馈的内容之后,它从内容中找到"Server对应的本地服务对象",然后调用该对象的onTransact()。不同的本地服务都可以实现自己的onTransact();这样,不同的服务就可以按照自己的需求来处理请求。
2.2 Binder通信
Binder通信协议是基于Command-Reply的方式的。
2.2.1 Binder通信模型

下面是Client和Server的交互模型图。

BC_TRANSACTION--->BR_TRANSACTION--->BC_REPLY--->BR_REPLY

相关源码:https://my.oschina.net/youranhongcha/blog/167314
2.2.2 Binder通信数据

上面是用户空间和内核空间进行交互时,数据的打包方式。例如,当Client向Server发送请求时,Client会将数据打包成上述格式,然后通过ioctl()发送给Binder驱动。根据数据的层次,从外到里分为3层进行说明。
第一层:这是用户空间的进程调用ioctl(fd,BINDER_WRITE_READ,&bwr)时传递给Binder驱动的信息。fd是Binder驱动的文件句柄,BINDER_WRITE_READ是ioctl()的一个标识,而bwr是传递的数据,它对应是图中的binder_write_read结构体的指针。
binder_write_read中以write开头的是保存请求数据的,而read开头的是保存反馈数据的。
其中,write_size是请求数据的大小,write_buffer是请求数据的内容,而write_consumed是用来记录请求数据中已经被Binder驱动处理过的数据的大小.
第二层:这层的数据是"事务指令"+"binder_transaction_data结构体"组成的.图中给出的事务指令是BC_TRANSACTION,表示该事务是请求.
如果是回复,则是BR_开头的,例如BR_TRANSACTION。binder_transaction_data是描述事务交互数据的结构体;例如,target是指定事务目标,用来表示这个事务是交给谁进行处理的;code是事务编码,用来表示这是一个什么样的事务(例如,注册服务事务/获取服务事务等待);data是保存事务中具体数据的内存地址。
第三层:这层是有效数据.如果该请求是传递给ServiceManager进行处理的,则有效数据是:消息头+"Server的相关信息".
消息头是用来进行有效性检查的,而"Server的相关信息"则是请求要处理的信息.

- 发起端进程:binder_transaction()过程将BC_TRANSACTION转换为BW_TRANSACTION;
- 接收端进程:binder_thread_read()过程,将BW_TRANSACTION转换为BR_TRANSACTION;
- 接收端进程:IPC.execute()过程,处理BR_TRANSACTION命令。
消息流程

svcinfo
说明:svcinfo是保存"注册到ServiceManager中的服务"的相关信息的结构体。它是一个单链表,在ServiceManager守护进程中的svclist是保存注册到ServiceManager中的服务的链表,它就是struct info类型。svcinfo中的next是指向下一个服务的节点,而ptr是该服务在Binder驱动中Binder引用的描述。name则是服务的名称。

int main(void)
{
int sockets[2],bufferSize = SOCKET_BUFFER_SIZE;
socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets);
setsockopt(sockets[0/1], SOL_SOCKET, SO_SNDBUF/SO_RCVBUF, &bufferSize, sizeof(bufferSize));
sp<MyThread> th = new MyThread(sockets[0]);// 创建线程, 和test_client使用socketpiar通信
th->run();
sp<ProcessState> proc(ProcessState::self());// 关键点1 初始化binder
sp<IServiceManager> sm = defaultServiceManager();// 关键点2 获得BpServiceManager
sm->addService(String16("hello"), new BnHelloService(sockets[1]));// 关键点3
ProcessState::self()->startThreadPool();//关键点4 创建新的子线程,并开始处理驱动上报的消息
IPCThreadState::self()->joinThreadPool();//辅助类 IPCThreadState的分析 // 关键点5 主线程 循环,循环并处理驱动上报的消息
}Android Binder机制(二) Binder中的数据结构
| 数据结构 | 说明 |
| binder_device | binder设备,系统初始化时会定义binder、hwbinder、vndbinder三个设备 |
| binder_context | binder上下文,每个binder设备包含一个上下文结构 |
binder_proc | binder进程记录,每个打开binder设备的进程均包含该结构,用来记录该进程的各种信息和状态。例如:线程表、binder节点表、节点引用表 binder_proc是描述Binder进程上下文信息的结构体。Binder驱动的文件节点是"/dev/binder",每当一个程序打开该文件节点时;Binder驱动中都会新建一个binder_proc对象来保存该进程的上下文信息。 proc表示这个线程所属的进程,把属于这个进程的所有线程都组织起来。binder_thread的rb_node表示binder 实体.| |
| binder_thread | binder线程,记录了线程相关的信息,例如需要完成的任务等. binder_thread是描述Binder线程的结构体。binder_proc是描述进程的,而binder_thread是描述进程中的线程。 说明:binder_thread是描述Binder线程相关信息的结构体。 (01) proc,它是binder_proc(进程上下文信息)结构体对象。目的是保存该线程所属的Binder进程。 (02) rb_node,它是红黑树节点。通过将rb_node binder关联到红黑树proc->threads中,从而将该线程添加到进程的threads红黑树中进行管理。 |
| binder_node | binder节点.binder_node是描述Binder实体的结构体。 说明:(02) proc,它是binder_proc(进程上下文信息)结构体对象。目的是保存该Binder实体的进程。 (03) refs,它是该Binder实体的所有引用所组成的链表。 在Binder驱动中,会为每一个Server都创建一个Binder实体,即会为每个Server都创建一个binder_node对象。 |
| binder_transaction | binder事务 |
| binder_buffer | binder缓冲区,由mmap创建,用于binder事务.描述Binder进程所管理的每段内存的结构体 |
| binder_alloc | binder proc的地址空间 |
| binder_ref | binder引用。binder_ref是描述Binder引用的结构体。 说明:(02) node是该Binder引用所引用的Binder实体。而node_entry在是关联到该Binder实体的binder_node->refs哈希表中。 "Binder实体"和"Binder引用"可以很好的将Server和Client关联起来:因为Binder实体和Binder引用分别是Server和Client在Binder驱动中的体现。 Client获取到Server对象后,"Binder引用所引用的Biner实体(即binder_ref.node)" 会指向 "Server对应的Biner实体";同样的,Server被某个Client引用之后,"Server对应的Binder实体的引用列表(即,binder_node.refs)" 会包含 "Client对应的Binder引用"。 |
| binder_write_read | binder_write_read是描述Binder读写信息的结构体。 说明:当用户空间的应用程序和Binder驱动通信时,它会将数据打包到binder_write_read中。 write开头的是记录应用程序要发送给Binder驱动的内容,而read开头的是记录Binder驱动要反馈给应用程序的内容。 |
| binder_transaction_data | 是描述Binder事务交互的数据格式的结构体。 |
| binder_mmap | get_vm_area,proc->pages = kzalloc,binder_update_page_range,list_add |
| binder_update_page_range | alloc_page,map_vm_area,vm_insert_page |
| binder_ioctl | wait_event_interruptible,binder_get_thread { case BINDER_WRITE_READ:copy_from_user,binder_thread_write,binder_thread_read} |
| binder_get_thread: | rb_entry,kzalloc,rb_link_node,rb_insert_color |
| binder_loop: | ioctl,binder_parse |
| binder_write : | ioctl(bs->fd, BINDER_WRITE_READ, &bwr) |
| joinThreadPool: | 这个函数最终是在一个无穷循环中,与Binder驱动程序进行交互,实际上就是调用talkWithDriver来等待Client的请求,然后再调用executeCommand来处理请求,而在executeCommand函数中,最终会调用BBinder::transact来真正处理Client的请求 |
| 从binder_thread_read返回来后,再看看proc->todo是否还有事务等待处理,如果是,就把睡眠在proc->wait队列的线程唤醒来处理。 最后,把本地变量struct binder_write_read bwr的内容拷贝回到用户传进来的缓冲区中,就返回了 |
1.7 binder_ioctl_write_read

三. 场景总结
数据传输

图(左)说明:
- AMP.startService: 将数据封装到Parcel类型;
- IPC.writeTransactionData:将数据封装到binder_transaction_data结构体;
- IPC.talkWithDriver:将数据进一步封装到binder_write_read结构体;
- 再通过ioctl()写入命令BINDER_WRITE_READ和binder_write_read结构体到驱动层
- binder_transaction: 将发起端数据拷贝到接收端进程的buffer结构体;
图(右)说明:
- binder_thread_read:根据binder_transaction结构体和binder_buffer结构体数据生成新的binder_transaction_data结构体,写入bwr的write_buffer,传递到用户空间。
- IPC.executeCommand: 解析binder_transaction_data数据,找到目标BBinder并调用其transact()方法;
- AMN.onTransact: 解析Parcel数据,然后调用目标服务的目标方法;
- AMS.startService: 层层封装和拆分后,执行真正的业务逻辑。
下面这图是从Binder在进程间数据通信的流程图,从图中更能明了Binder的内存转移关系

Binder进程与线程

2. 用户空间的Binder数据结构
2.2 C++层的数据结构
2.2.1 Parcel
Parcel是描述Binder通信信息的结构体
Android Binder机制(三) ServiceManager守护进程
service命令使用,请自行搜索+link

Android Binder机制(四) defaultServiceManager()的实现
defaultServiceManager 等价于 new BpServiceManager(new BpBinder(0));
获取Service Manager远程接口的函数是defaultServiceManager
BpServiceManager巧妙将通信层与业务层逻辑合为一体,
- 通过继承接口
IServiceManager实现了接口中的业务逻辑函数; - 通过成员变量
mRemote= new BpBinder(0)进行Binder通信工作。 - BpBinder通过handler来指向所对应BBinder, 在整个Binder系统中
handle=0代表ServiceManager所对应的BBinder。
defaultServiceManager()获取到的,不是"ServiceManager进程",而是"IServiceManager对象"。"ServiceManager进程"是一个守护进程,而defaultServiceManager()获取到的是C++层的IServiceManager类的一个实例。当然,通过该defaultServiceManager()返回的"IServiceManager对象"是可以和ServiceManager进行通信的。
defaultServiceManager概述
1. defaultServiceManager流程图

上面是defaultServiceManager()的时序图。
defaultServiceManager()会返回一个sp类型的对象。
IServiceManager提供了addService()供MediaPlayerService等服务注册到ServiceManager中,提供了getService()供MediaPlayer等MediaPlayer等客户端获取服务。
a) 它首先会调用ProcessState::self()单例模式,open /dev/binder
b) 在获取到ProcessState对象之后,会通过该对象调用getContextObject()来获取一个IBinder对象。getContextObject()会调用getStrongProxyForHandle(0)来获取"句柄0的强引用代理对象",这里的句柄0被赋予了特殊意义;它就是ServiceManager的句柄,在Binder驱动中,若获取到句柄的值是0,则会将其目标当作是ServiceManager。
简而言之,getContextObject()的目的就是获取ServiceManager对应的BpBinder代理对象。
1.2 defaultServiceManager相关类的类图
对于一个Server而言,它都会存在一个"远程BpBinder对象"和"本地BBinder对象"。
(01) 远程BpBinder对象的作用,是和Binder驱动进行交互。
具体的方式是,当Server要向Binder发起事务请求时,会调用BpBinder的transact()接口,而该接口会调用到IPCThreadState::transact()接口,通过IPCThreadState类来和Binder驱动交互。
此外,该BpBinder在Binder驱动中的Binder引用的描述会被保存到ProcessState的mHandleToObject矢量缓冲数组中.
(02) 本地BBinder对象的作用,是Server响应Client请求的类。
当Client有请求发送给Server时,都会调用到BBinder的onTransact()函数,而每个Server都会覆盖onTransact()函数。这样,每个Server就可以在onTransact()中根据自己的情况对请求进行处理。
Android Binder机制(五) addService详解01之 请求的发送(addService 请求发送,处理,反馈)
- 接着在正式开始进行源码分析前,先看看Native Binder类图如下:

二.IMediaPlayerService的类图

client端:BpBinder.transact()来发送事务请求;server端:BBinder.onTransact()会接收到相应事务
Android Binder机制(九) getService详解01之 请求的发送 (发送,处理,反馈)

1.2.2 Android Java层Binder类图
Android Binder框架实现之Framework层Binder服务注册过程源码分析


system_server进程和servicemanager进程之间的关系图如下:

一.AMP跨进程调用AMS服务流程分析
1.1 AMP服务代理端的获取

Android Binder框架实现之Java层获取Binder服务源码分析

SMP(name)--->
Binder驱动--->
servicemanager(handle)--->
Binder驱动--->servicemanger(binder_ref)--->binder_node--->JavaBBinder
AIDL
binder:线程池在用户空间创建,内核空间管理

自定义service
自定义的service添加do_add_service
do_add_service
si = find_svc(s, len);//当找到服务的handle, 则调用bio_put_ref(reply, handle),将handle封装到reply
si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
......
si->next = svclist; // svclist保存所有已注册的服务
那么多的binder 读写函数不需要在这里介
others:
驱动层开发就是调用内核函数eg: copy_to_user,kzmalloc,ioctl(read/write).
有几个驱动层的步骤,eg:open设备; node节点;红黑树(类似文件操作)
附录: http://gityuan.com/android/




引用:http://gityuan.com/2015/10/31/binder-prepare/
图文详解 Android Binder跨进程通信的原理 https://www.jianshu.com/p/4ee3fd07da14




