Binder源码分析

在这里插入图片描述

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通信

源码分析
binder_ipc_process

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....小结流程.
对于所有数据结构统一注释,类的每个变量注释.而且写的都是选过的了,看的更多.
所以源码工作者上面的工作量很多。转载希望能分享给更多人
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

目录

0Binder系列—开篇Binder概述
1Binder系列3—启动Service ManagerServiceManager守护进程 注册和查询服务
2Binder系列4—获取Service Manager获取代理对象BpServiceManager
3Binder系列5—注册服务(addService)注册Media服务
4Binder系列6—获取服务(getService)获取Media代理,以及DeathRecipient
5Binder系列7—framework层分析framework层服务注册和查询,Binder注册
6理解Binder线程池的管理Binder的startThreadPool过程
7彻底理解Android Binder通信架构startService为主线
8Binder系列10—总结Binder的简单总结
9Binder IPC的权限控制clearCallingIdentity/restoreCallingIdentity
10Binder死亡通知机制之linkToDeathBinder死亡通知机制

Binder使用篇:

1Binder系列8—如何使用BinderNative层、Framwrok层自定义Binder服务
2Binder系列9—如何使用AIDLApp层自定义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端。

  1. 注册服务(addService):Server进程要先注册Service到ServiceManager。该过程:Server是客户端,ServiceManager是服务端。
  2. 获取服务(getService):Client进程使用某个Service前,须先向ServiceManager中获取相应的Service。该过程:Client是客户端,ServiceManager是服务端。
  3. 使用服务:Client根据得到的Service信息建立与Service所在的Server进程通信的通路,然后就可以直接与Service交互。该过程:client是客户端,server是服务端。

,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,

ServiceManager

Service启动的过程就是向binder驱动注册的过程.

1 流程图

create_servicemanager

这里写图片描述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启动过程主要以下几个阶段:

  1. 打开binder驱动:binder_open;
  2. 注册成为binder服务的大管家:binder_become_context_manager;
  3. 进入无限循环,处理client端发来的请求:binder_loop

ServiceManager最核心的两个功能为查询和注册服务:

  • 注册服务:记录服务名和handle信息,保存到svclist列表;
  • 查询服务:根据服务名查询相应的的handle信息。

2 启动过程

ServiceManager是由init进程通过解析init.rc文件而创建的

2.1 binder 建立:

主要是驱动设备的初始化(binder_init),打开 (binder_open),映射(binder_mmap),数据操作(binder_ioctl)。

binder_driver

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_nodenode->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 流程图

get_servicemanager

四 注册服务(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的整个的类关系图

add_media_player_service

图解:

  • 蓝色代表的是注册MediaPlayerService服务所涉及的类
  • 绿色代表的是Binder架构中与Binder驱动通信过程中的最为核心的两个类;
  • 紫色代表的是注册服务和获取服务的公共接口/父类;

时序图

先通过一幅图来说说,media服务启动过程是如何向servicemanager注册服务的。

addService

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。
通信流程图如下所示:

media_player_service_ipc

过程分析:

  1. MediaPlayerService进程调用ioctl()向Binder驱动发送IPC数据,该过程可以理解成一个事务binder_transaction(记为T1),执行当前操作的线程binder_thread(记为thread1)。其中IPC数据内容包含:
    • Binder协议为BC_TRANSACTION;
    • Handle等于0;
    • RPC代码为ADD_SERVICE;
    • RPC数据为”media.player”。
  2. Binder驱动收到该Binder请求,生成BR_TRANSACTION命令,选择目标处理该请求的线程,即ServiceManager的binder线程(记为thread2).并将整个binder_transaction数据(记为T2)插入到目标线程的todo队列

  3. Service Manager的线程thread2收到T2后,调用服务注册函数将服务”media.player”注册到服务目录中。当服务注册完成后,生成IPC应答数据(BC_REPLY)

  4. 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层所涉及的全部类

java_binder_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线程的创建流程图:

binder_thread_create

每次由Zygote fork出新进程的过程中,伴随着创建binder线程池,调用spawnPooledThread来创建binder主线程。
当线程执行binder_thread_read的过程中,发现当前没有空闲线程,没有请求创建线程,且没有达到上限,则创建新的binder线程。

Android Binder通信架构

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

主要功能:

  1. 查询目标进程的过程: handle -> binder_ref -> binder_node -> binder_proc
  2. BINDER_WORK_TRANSACTION添加到目标队列target_list:
    • call事务, 则目标队列target_list=target_proc->todo;
    • reply事务,则目标队列target_list=target_thread->todo;
    • async事务,则目标队列target_list=target_node->async_todo.
  3. 数据拷贝
    • 将用户空间binder_transaction_data中ptr.buffer和ptr.offsets拷贝到目标进程的binder_buffer->data;
    • 这就是只拷贝一次的真理所在;
  4. 设置事务栈信息
    • BC_TRANSACTION且非oneway, 则将当前事务添加到thread->transaction_stack;
  5. 事务分发过程:
    • BINDER_WORK_TRANSACTION添加到目标队列(此时为target_proc->todo队列);
    • BINDER_WORK_TRANSACTION_COMPLETE添加到当前线程thread->todo队列;
  6. 唤醒目标进程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_ipc_process

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

通信协议

从通信协议的角度来看这个过程:

binder_transaction

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

说一说oneway

上图是非oneway通信过程的协议图, 下图则是对于oneway场景下的通信协议图:

binder_transaction_oneway

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

数据流

binder_transaction_data

  • 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_transaction

在Binder驱动层,每个接收端进程都有一个todo队列,用于保存发送端进程发送过来的binder请求,
这类请求可以由接收端进程的任意一个空闲的binder线程处理;
接收端进程存在一个或多个binder线程,在每个binder线程里都有一个todo队列,也是用于保存发送端进程发送过来的binder请求,这类请求只能由当前binder线程来处理。
binder线程在空闲时进入可中断的休眠状态,当自己的todo队列或所属进程的todo队列有新的请求到来时便会唤醒,
如果是由所需进程唤醒的,那么进程会让其中一个线程处理响应的请求,其他线程再次进入休眠状态

Binder路由

先来看看Native Binder IPC的两个重量级对象:BpBinder(客户端)和BBinder(服务端)都是Android中Binder通信相关的代表,它们都从IBinder类中派生而来,关系图如下:

Binder关系图

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

binder_protocol

相关源码:https://my.oschina.net/youranhongcha/blog/167314

2.2.2 Binder通信数据

binder_protocol

上面是用户空间和内核空间进行交互时,数据的打包方式。例如,当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的相关信息"则是请求要处理的信息.

protocol_transaction.jpg

  • 发起端进程: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_devicebinder设备,系统初始化时会定义binder、hwbinder、vndbinder三个设备
binder_contextbinder上下文,每个binder设备包含一个上下文结构

binder_proc

binder进程记录,每个打开binder设备的进程均包含该结构,用来记录该进程的各种信息和状态。例如:线程表、binder节点表、节点引用表

binder_proc是描述Binder进程上下文信息的结构体。Binder驱动的文件节点是"/dev/binder",每当一个程序打开该文件节点时;Binder驱动中都会新建一个binder_proc对象来保存该进程的上下文信息。
这个结构体包括,server,client binder的红黑树树根。
todo 链表:它是该进程的待处理事务队列,而wait则是等待队列。它们的作用是实现进程的等待/唤醒。
例如,当Server进程的wait等待队列为空时,Server就进入中断等待状态;
当某Client向Server发送请求时,就将该请求添加到Server的todo待处理事务队列中,并尝试唤醒Server等待队列上的线程.
如果,此时Server的待处理事务队列不为空,则Server被唤醒后;唤醒后,则取出待处理事务进行处理,处理完毕,则将结果返回给Client.

proc表示这个线程所属的进程,把属于这个进程的所有线程都组织起来。binder_thread的rb_node表示binder 实体.|
struct binder_proc有一个成员变量threads,它表示一个红黑树,把属于这个进程的所有线程都组织起来。
rb_node是Binder实体;refs成员变量把所有引用了该Binder实体的Binder引用连接起来构成一个链表.

binder_threadbinder线程,记录了线程相关的信息,例如需要完成的任务等.
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_nodebinder节点.binder_node是描述Binder实体的结构体。
说明:(02) proc,它是binder_proc(进程上下文信息)结构体对象。目的是保存该Binder实体的进程。
(03) refs,它是该Binder实体的所有引用所组成的链表。
在Binder驱动中,会为每一个Server都创建一个Binder实体,即会为每个Server都创建一个binder_node对象。
binder_transactionbinder事务
binder_bufferbinder缓冲区,由mmap创建,用于binder事务.描述Binder进程所管理的每段内存的结构体
binder_allocbinder proc的地址空间
binder_refbinder引用。binder_ref是描述Binder引用的结构体。

说明:(02) node是该Binder引用所引用的Binder实体。而node_entry在是关联到该Binder实体的binder_node->refs哈希表中。
(03) proc,它是binder_proc(进程上下文信息)结构体对象。目的是保存该Binder引用所属的进程。
在Binder驱动中,会为每个Client创建对应的Binder引用,即会为每个Client创建binder_ref对象。

"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引用"。
notes: server,client 建立连接以后.两个struct各自增加一个指向对方的item.

binder_write_readbinder_write_read是描述Binder读写信息的结构体。
说明:当用户空间的应用程序和Binder驱动通信时,它会将数据打包到binder_write_read中。
write开头的是记录应用程序要发送给Binder驱动的内容,而read开头的是记录Binder驱动要反馈给应用程序的内容。
binder_transaction_data

是描述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_ioctlwait_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


binder_write_read

三. 场景总结

数据传输

binder_dataflow.jpg

图(左)说明:

  • 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_memory_map

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/

传输机制篇_下003

6rd_binder_transaction

在这里插入图片描述

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


版权声明:本文为fdsafwagdagadg6576原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。