码迷,mamicode.com
首页 > 其他好文 > 详细

大话Binder机制

时间:2016-05-30 15:42:21      阅读:330      评论:0      收藏:0      [点我收藏+]

标签:


注意以下内容中出现的类和部分类的方法只能在Android源码中或者通过反射机制才能使用,在SDK中编译是通不过的!!如Android.os.Service; MemeoryFile.getParcelFileDescriptor()等你在SDK中无法使用!这里的内容只是帮助我们去了解Service、ContentProvider等功能为何能实现跨进程间的通信;它们无非就是通过Binder机制和虚拟内存实现的!!

简介

传统Linux系统的IPC方式 VS Android
  • 传统的管道(Pipe)、信号(Signal)和跟踪(Trace),这三项通信手段只能用于父进程与子进程之间,或者兄弟进程之间
  • 报文队列(Message)、共享内存(Share Memory)和信号量(Semaphore),插口(Socket)的进程间通信机制;
  • Android系统没有采用上述提到的各种进程间通信机制,而是采用Binder机制,只需要复制一次效率更高。
Binder组件:
  • 核心组件是Binder驱动程序,运行内核空间;
  • Client、Server和Service Manager运行在用户空间
  • Service Manager是一个守护进程,用来管理Server,并向Client提供查询Server接口的能力;
  • Client和Server在Binder驱动和Service Manager提供的基础设施上,进行Client-Server之间的通信;
  • Service Manager和Binder驱动已经在Android平台中实现好,开发者只要按照规范实现自己的Client和Server组件;(依然很困难)
  • 具体结构如下
技术分享


实例(Java层应用)

     用户定义了一个aidl文件(如 MyServe.aidl (interface MyServe))随后编译后我们得到了一个对应的java类(如MyServe.java)。Activity通过bindService方法获得一个远程Service的IBinder对象;通过调用com.yq.MyServe.Stub.asInterface(iBinder);获得一个MyServe接口的对象,方法内部会判断返回给你一个继承自Stub的类——与Acitivity在同一个进程,还是一个Proxy(将远程调用另一个进程的继承自Stub的类,通过Parcel传递数据)对象。具体aidl编译后的文件内容为MyServe.java文件内容如下:
public interface MyServe extends android.os.IInterface
  • public static abstract class Stub extends android.os.Binder implements MyServe //服务端跑的代码
    • private static final java.lang.String DESCRIPTOR = "com.yq.MyServe";
    • public static MyServe asInterface(android.os.IBinder obj)
    • {
    • if ((obj==null)) { return null; 
    • android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
    • if (((iin!=null)&&(iin instanceof com.yq.MyServe))) return ((com.yq.MyServe)iin);  //客户端是本地的一个进程;返回本地的MyServe对象
    • return new com.yq.MyServe.Stub.Proxy(obj); //客户端是另外一个进程;创建一个MyServe.Stub.Proxy对象返回
    • }
    • public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
    • {//code对应方法的签名;data对应参数;reply对应返回值
    • switch (code)
    • {
    •    case INTERFACE_TRANSACTION: xx
    •           //调用相关方法,从data获取数据,向reply写入数据;
    • }
    • }
    • private static class Proxy implements com.yq.MyServe //另外一个进程,客户端跑的代码
      • private android.os.IBinder mRemote;
      • Proxy(android.os.IBinder remote)  mRemote = remote; } //获得外部类Stub的一个对象

      • public int getxx() throws android.os.RemoteException //比如客户端调用了这个方法,内部其实走的是这样的
      • {
      • android.os.Parcel _data = android.os.Parcel.obtain();
      • android.os.Parcel _reply = android.os.Parcel.obtain();
      • int _result;
      • try {
      • _data.writeInterfaceToken(DESCRIPTOR); //写入参数
      • mRemote.transact(Stub.TRANSACTION_getPid, _data, _reply, 0);  
      • //调用Stub对象的transact方法,其实最后是会调用上面的onTransact方法;最核心的东西
      • //Stub.TRANSACTION_getPid对应onTransact方法的code
      • //_data对应onTransact方法的data
      • //_reply对应onTransact方法的reply
      • _reply.readException();
      • _result = _reply.readInt();  //从reply中读出数据
      • }
      • finally {
      • _reply.recycle();
      • _data.recycle();
      • }
      • return _result; //返回结果,客户端最后获得这个结果
      • }
注意:如果要利用Binder在进程之间传递对象,那么需要实现Parcelable接口:如果通过Bundle传递该对象(putParcelable),当通过getParcelable获取该对象的时候需要先给Bundle设置类加载(setClassLoader),这在跨进程之间通信显得尤为重要。
public class MyParcelable implements Parcelable {
     private int mData;
     public int describeContents() {
         return 0;
     }
     public void writeToParcel(Parcel out, int flags) {
         out.writeInt(mData);
     }
     public static final Parcelable.Creator<MyParcelable> CREATOR = new Parcelable.Creator<MyParcelable>() { 
         public MyParcelable createFromParcel(Parcel in) {
             return new MyParcelable(in);
         }
         public MyParcelable[] newArray(int size) {
             return new MyParcelable[size];
         }
     };
     private MyParcelable(Parcel in) {
         mData = in.readInt();
     }
 }


底层源码分析

在正式的分析之前首先做出如下约定:
  • Binder机制中进行如下的分层:用户层、Binder层、IPCThreadState层、Binder驱动层
  • 本文中使用的“Binder层协议”关键字表示该协议主要在Binder程序中出现。
    • 这类协议常用的有:ADD_SERVICE_TRANSACTION、CHECK_SERVICE_TRANSACTION
  • 本文中使用的“IPCThreadState层协议”关键字表示该协议主要在IPCThreadState程序中出现。
    • 这类协议常用的有:BC_TRANSACTION、BR_TRANSACTON、BR_TRANSACTON_COMPLETE、BC_REPLY
  • 本文中使用的“Binder驱动协议”关键字表示该协议主要在Binder驱动程序中出现。
    • 这类协议常用的有:BINDER_SET_CONTEXT_MGR、BINDER_WRITE_READ、
 
Client端通信流程:
  1. Client进程在用户层将通信数据封装成Parcelable对象;
  2. Client进程将第一步获得的Parcelable对象交给Binder层处理(通过调用IBinder的transact方法进入Binder层)。Binder层在对数据进行必要的处理之后,将处理后得到的数据加上一个相关的Binder层协议头交给IPCThreadState层处理(调用IPCThreadState的Transact方法进入IPCThreadState层);【涉及的Binder层协议有:CHECK_SERVICE_TRANSACTION、GET_SERVICE_TRANSACTION、ADD_SERVICE_TRANSACTION、LIST_SERVICES_TRANSACTION】
  3. Client进程的IPCThreadState层也会对数据进行必要的处理之后,并将处理后得到的数据加上一个相关的IPCThreadState层协议头交给Binder驱动层进行处理(调用ioctl方法进入Bidner驱动层)。同时IPCThreadState层会一直等待来自Binder驱动层返回的数据,如果Client的请求需要有返回值那么IPCThreadState层只需要接收两条数据才可以返回,否则一般情况接收到一条数据就可以结束这次的进程间通信。【涉及的IPCThreadState层协议有:BC_TRANSACTION、BR_TRANSACTION_COMPLETE、BR_REPLY、BR_TRANSACTION、BC_REPLY】

Server端通信流程:
  • Service通过IPCThreadState::joinThreadPool方法进入循环体中;
  1. Server进程的IPCThreadState层不断跟Binder驱动层进行交互(icotl方法根据参数的不同可能会导致阻塞),一旦获取到数据就交给IPCThreadState层的executeCommand方法进行处理,根据接收到的数据所属IPCThreadState层的哪个协议进行对应的处理。如接收到BR_TRANSACTION协议报文表明这是一个Binder发送来的请求Service处理的协议报文,IPCThreadState层会将得到的数据擦去IPCThreadState层协议头,然后交给Binder层处理处理(通过调用BBinder的transact方法,BBinder是通过发送来的BR_TRANSACTION协议报文得到的对象)。Binder层对数据处理完毕后,IPCThreadState层将Binder层处理后的数据加上一个BR_REPLY协议头,发送给Binder驱动层,同时等待Binder驱动层返回一条BR_TRANSACTON_COMPLETE协议报文结束这次进程间通信。
  2. BBinder的transact方法内部会调用其子类(对应Server端的BnXXX)的onTransact方法处理。onTransact方法内部根据接收到的数据所属哪个Binder层协议,对数据进行不同的处理,这里可以调用用户层的相关业务。方法执行完毕后回将到IPCThreadState层,调用IPCThreadState的sendReply方法返回处理后的数据给Binder驱动层。

Client&Server通信流程(IPCThreadState层)——任何进程间通信都是下面的固定步骤
  1. Client进程将通信数据封装成Parcelable对象;
  2. Client进程向Binder驱动程序发送一个BC_TRANSACTION命令协议。Binder驱动根据协议内容找到目标Server进程后,向Client发送一个BR_TRANSACTON_COMPLETE返回协议,表示它的进程间请求已经被接受。Client对返回的BR_TRANSACTON_COMPLETE协议进行处理过后,就会再次进入Binder驱动程序中等待目标Server进程返回进程间通信结果。这个过程Binder会将Client端数据拷贝到Service通过mmap申请得到的那块物理空间、Binder驱动将前面得到的物理空间对应的虚拟地址传递给Service的用户空间;Binder对数据的拷贝只会发生在这一个地方
  3. Binder驱动程序在向Client发送BR_TRANSACTON_COMPLETE的同时会向Server发送一个BR_TRANSACTON协议,请求目标Server进程处理进程间通信请求。
  4. Server进程接收到Binder驱动程序发来的BR_TRANSACTON协议,并对它处理之后就会向Binder驱动程序发送一个BC_REPLY命令协议。Binder驱动程序根据BC_REPLY协议内容找到目标Client目标后,会向Server进程发送一个BR_TRANSACTON_COMPLETE协议,表示 它返回的通信结果已经收到。Server对BR_TRANSACTON_COMPLETE协议内容处理过后,一次进程间通信就结束了。接着再次进入驱动程序等待下一次进程间通信请求。
  5. Binder驱动程序在向Server进程发送一个BR_TRANSACTON_COMPLETE协议的同时会向Client发送BR_REPLY返回协议,并且将结果返回给Client。


正式对源码进行分析之前,首先对Binder机制中经常出现的几个类和接口进行简单的说明:
{ binder / IInterface.h}
class IInterface : public virtual RefBase

template<typename INTERFACE>  //INTERFACE为自定义的一个接口继承IInterface
class BnInterface : public INTERFACE, public BBinder

template<typename INTERFACE>  ///INTERFACE为自定义的一个接口继承IInterface
class BpInterface : public INTERFACE, public BpRefBase

INTERFACE是进程自定义的Service组件接口、BBinder为Binder本地对象提供了抽象的进程间通信接口、BpRefBase为Binder代理对象提供了抽象的进程间通信接口。
BnInterface为Binder本地对象, Service端使用,对应Binder驱动程序中的Binder实体对象;BpInterface为Binder代理对象,Client端使用,对应Binder驱动程序中的Binder引用对象。用户需要编写一个BnXXXX实现BnInterface<INTERFACE>和一个BpXXXX实现BpInterface<INTERFACE>的类,前者Service端使用,后者Client端使用。
BBinder@{ binder / Binder.h}
class BBinder : public IBinder{ 
public:  ``````````````
    virtual status_t    transact(   uint32_t code,  const Parcel& data,  Parcel* reply,  uint32_t flags = 0); 
    //IPCThreadState就会代用BBinder子类的该方法,该方法内部会调用BnXXXX对onTransact方法的实现。
protected:  ````````````
    virtual status_t    onTransact( uint32_t code,  const Parcel& data, Parcel* reply,  uint32_t flags = 0); 
    //BnXXXX实现BnInterface<INTERFACE>时就会定义该方法
};


BpRefBase@{ binder / Binder.h}
class BpRefBase : public virtual RefBase { 
protected: ·······
     BpRefBase(const sp<IBinder>& o);
    inline  IBinder*        remote(){ return mRemote; }
private: ······
    BpRefBase(const BpRefBase& o);
    IBinder* const          mRemote; //note1
};

1、指向一个BpBinder对象
BpBinder@{ binder / BpBinder.h}
class BpBinder : public IBinder { 
public: ·········
    inline  int32_t     handle() const { return mHandle; }
    virtual status_t    transact(   uint32_t code,  const Parcel& data, Parcel* reply, uint32_t flags = 0); //note2
private: ·······
    const   int32_t     mHandle; //note1
};
1、该整数表示一个Client组件的句柄值。每一个Client组件在驱动程序对应一个Binder引用对象。
2、BpBinder的transact方法会把自己的mHandler和进程间通信数据发送给Binder驱动程序。Binder驱动程序根据mHandler找到对应的Binder引用对象,进而找到Binder实体对象(Binder驱动层能够完成BpBinder到BBinder之间的映射,最后将通信数据发送给Service组件。(对于如何通过BpBinder找到BBBinder推荐查阅博文,搜索关键字sp<BBinder> b((BBinder*)tr.cookie)即可
BBinder和BpBinder都是通过IPCThreadSate来和Binder驱动程序交互。
IPCThreadState @{ binder / IPCThreadState.h }
class IPCThreadState { 
public: ········
    static  IPCThreadState*     self(); 
     //当前线程是Binder线程,通过它获取一个IPCThreadState对象,该对象可以跟Binder驱动层通信。
    status_t   transact(int32_t handle,  uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags); 
    //与Binder驱动程序交互,底层通过talkWithDriver实现
private:············
    status_t            sendReply(const Parcel& reply, uint32_t flags);
    status_t            waitForResponse(Parcel *reply,  status_t *acquireResult=NULL); 
    status_t            talkWithDriver(bool doReceive=true); //向Binder驱动发送数据也从Binder驱动接收数据
    status_t            writeTransactionData(int32_t cmd, uint32_t binderFlags, 
                                                     int32_t handle,
                                                     uint32_t code,
                                                     const Parcel& data,
                                                     status_t* statusBuffer);
    status_t            executeCommand(int32_t command);
    const   sp<ProcessState>    mProcess; //初始化Binder设备
};
对于每个Binder线程池中它都有一个IPCThreadState对象
Service组件结构图
技术分享技术分享

Client组件结构图
技术分享
上面的分析我们可以简单的获得以下几个结论:
  • Server端:BnXXX.cpp需要实现IXX的自定义方法和BBinder的onTransact方法;BBinder自己实现了transact方法,但是transact方法内部会调用onTransact方法。
  • Client端:BpXXX.cpp需要实现IXX的自定义方法,方法内部是将数据包装之后利用BpRefBase的remote方法获得一个BpBinder,随后调用BpBinder的tranact方法将数据发送给Binder驱动程序。
  • BBinder和BpBinder跟Binder驱动的通信都是通过IPCThreadState来实现的,通过IPCThreadState:self()方法获取该对象,注意通信的前提Client和Server端的主线程已经注册为Binder线程。

要知道Service、Client、Service Manager等用户态都是通过open、mmap、ioctl访问Binder驱动程序的。而open对应binder_open、mmap对应binder_mmap、ioctl对应binder_ioctl定义在android / binder.c文件中。下面重点分析一下ServiceManager的注册和相关重要方法!

service_manager.c

    Binder通信机制使用句柄来代表远程接口,Service Manager在充当守护进程的同时,它充当Server的角色,当它作为远程接口使用时,它的句柄值便为0,这就是它的特殊之处,其余的Server的远程接口句柄值都是一个大于0 而且由Binder驱动程序自动进行分配的。init进程负责启动ServiceManager,init进程是在系统启动时启动,因此ServiceManager在系统启动的时候跟随系统一同启动。
main()@{servicemanager / service_manager.c}
void *svcmgr_handle; //ServerManager.c的一个局部变量
int main(int argc, char **argv)
{
    struct binder_state *bs; //note 1
    void *svcmgr = BINDER_SERVICE_MANAGER; //note2
    bs = binder_open(128*1024); //note3
    if (binder_become_context_manager(bs)) { //note4
        return -1;
    }
    svcmgr_handle = svcmgr; //note5
    binder_loop(bs, svcmgr_handler); //note6
    return 0;
}
1、
struct binder_state{
    int fd; //设备描述符
    void *mmaped; //映射空间起始地址
    unsigned mapsize; //映射空间大小
    //映射是将设备文件映射到进程的地址空间,用于缓存进程间通信的数据
}

2、#define BINDER_SERVICE_MANAGER ((void*) 0)  //句柄值为0的宏定义
3、打开Binder设备文件;open("/dev/binder", O_RDWR);建立128K内存映射mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
4、告诉Binder驱动程序自己是Binder上下文管理者,即我们前面所说的守护进程;binder_become_context_manager(bs);
5、保存到全局变量中,一个与ServiceManager对应的虚拟Binder本地对象
6、是进入一个无穷循环,充当Server的角色,等待Client的请求。binder_loop(bs, svcmgr_handler);
下面是对binder_open、binder_become_context_manager、binder_loop进行介绍
binder_open()@{ servicemanager / binder.c}
struct binder_state *binder_open(unsigned mapsize)
{
    struct binder_state *bs;
    bs = malloc(sizeof(*bs));
    if (!bs) { errno = ENOMEM;  return 0; }

    bs->fd = open("/dev/binder", O_RDWR); //note1
    if (bs->fd < 0) {  fprintf(stderr,"binder: cannot open device (%s)\n",strerror(errno)); goto fail_open; }
    bs->mapsize = mapsize;

    bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0); //note2
    if (bs->mapped == MAP_FAILED) {fprintf(stderr,"binder: cannot map device (%s)\n", strerror(errno)); goto fail_map;}
    return bs;

fail_map:
    close(bs->fd);
fail_open:
    free(bs);
    return 0;
}
1、该方法最终导致Binder驱动程序的binder_open方法被调用
binder_become_context_manager()@{ servicemanager / binder.c}
#define BINDER_SET_CONTEXT_MGR _IOW('b', 7, int)
int binder_become_context_manager(struct binder_state *bs)
{
    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0); //note1
}
1、该方法会导致Binder驱动的binder_ioctl方法被调用。binder_ioctl方法多次被使用到,已经贴在后面的附录一中。
通过向Binder驱动层发送BINDER_SET_CONTEXT_MGR协议将自己注册到Binder驱动程序中。ioctl中最后一个参数,表示当前Service Manager对应的本地Binder对象的地址值,Service Manager对应Binder本地对象值为0;

binder_loop()@{ servicemanager / binder.c}
BC_ENTER_LOOPER = _IO('c', 12),
BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read)
void binder_loop(struct binder_state *bs, binder_handler func){
    int res;
    struct binder_write_read bwr;
    unsigned readbuf[32];

    bwr.write_size = 0;
    bwr.write_consumed = 0;
    bwr.write_buffer = 0;
    
    readbuf[0] = BC_ENTER_LOOPER;
    binder_write(bs, readbuf, sizeof(unsigned));//note1

    for (;;) {
        bwr.read_size = sizeof(readbuf);
        bwr.read_consumed = 0;
        bwr.read_buffer = (unsigned) readbuf;

        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);  //note2
        if (res < 0) {  LOGE("binder_loop: ioctl failed (%s)\n", strerror(errno)); break; }

        res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func);  //note3
        if (res == 0) { LOGE("binder_loop: unexpected reply?!\n"); break;}
        if (res < 0) { LOGE("binder_loop: io error %d %s\n", res, strerror(errno)); break; }
    }
}

1、该方法用于将当前线程注册到Binder驱动程序中,成为Binder线程,Binder驱动程序随后可以将进程间通信请求交付给该线程进行处理
int binder_write(struct binder_state *bs, void *data, unsigned len)
{
    struct binder_write_read bwr;
    int res;
    bwr.write_size = len;
    bwr.write_consumed = 0;
    bwr.write_buffer = (unsigned) data;
    bwr.read_size = 0; //输出缓存区为空,则一旦完成注册,就会退回到用户空间中。
    bwr.read_consumed = 0;
    bwr.read_buffer = 0;
    res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); //note1
    if (res < 0) {
        fprintf(stderr,"binder_write: ioctl failed (%s)\n", strerror(errno));
    }
    return res;
}
1、向Binder驱动层发送一个BINDER_WRITE_READ协议报文
2、该方法的bwr参数的输出缓存区长度为readbuf大小,输入缓存区长度等于0,因此只会调用函数binder_thread_read如果ServiceManager进程的主线程没有待处理的工作项,它将会睡眠在Binder驱动程序的binder_thread_read中,等待其它Service和Client向它发送进程间通信请求。
3、解析获得的readbuf数据,使用binder_handler func处理
binder_parse()@{ servicemanager / binder.c}
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_NOOP:
            break;
        case BR_TRANSACTION_COMPLETE:
            break;
        case BR_INCREFS:
        case BR_ACQUIRE:
        case BR_RELEASE:
        case BR_DECREFS:
            ptr += sizeof(struct binder_ptr_cookie);
            break;
        case BR_TRANSACTION: {  //note1
            struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
            if ((end - ptr) < sizeof(*txn)) {  return -1;  } 
            binder_dump_txn(txn);
            if (func) {
                unsigned rdata[256/4];
                struct binder_io msg;
                struct binder_io reply;
                int res;
                bio_init(&reply, rdata, sizeof(rdata), 4);
                bio_init_from_txn(&msg, txn);
                res = func(bs, txn, &msg, &reply); //note2
                binder_send_reply(bs, &reply, txn->data.ptr.buffer, res); //note3
            }
            ptr += sizeof(*txn);
            break;
        }
        case BR_REPLY: {
            ......
            break;
        }
        case BR_DEAD_BINDER: {
           ........
            break;
        }
        case BR_FAILED_REPLY:
            r = -1;
            break;
        case BR_DEAD_REPLY:
            r = -1;
            break;
        default:
            return -1;
        }
    }
    return r;
}
1、接收到一个IPCThreadState层协议——BR_TRANSACTION;
2、调用func处理,func等于servicemanager / service_manager.c的svcmgr_handle对象。
3、向Binder驱动器发送BC_REPLY协议报文
svcmgr_handler()@{ servicemanager / service_manager.c}
int svcmgr_handler(struct binder_state *bs, struct binder_txn *txn, struct binder_io *msg,  struct binder_io *reply) {
    struct svcinfo *si;
    uint16_t *s;
    unsigned len;
    void *ptr;
    uint32_t strict_policy;
    if (txn->target != svcmgr_handle)  return -1; 
    strict_policy = bio_get_uint32(msg);
    s = bio_get_string16(msg, &len);
    if ((len != (sizeof(svcmgr_id) / 2)) ||
        memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
        fprintf(stderr,"invalid id %s\n", str8(s));
        return -1;
    }
    switch(txn->code) {
    case SVC_MGR_GET_SERVICE:
    case SVC_MGR_CHECK_SERVICE:
        s = bio_get_string16(msg, &len);
        ptr = do_find_service(bs, s, len); //从列表中查找服务
        if (!ptr)   break; 
        bio_put_ref(reply, ptr); //这里是{servicemanager / binder.c}中的方法;ptr是句柄号,将内容写入到reply中。
        return 0;
    case SVC_MGR_ADD_SERVICE:
        s = bio_get_string16(msg, &len);
        ptr = bio_get_ref(msg);
        if (do_add_service(bs, s, len, ptr, txn->sender_euid))  return -1;  
        break;
    case SVC_MGR_LIST_SERVICES: {
        unsigned n = bio_get_uint32(msg);
        si = svclist;
        while ((n-- > 0) && si)
            si = si->next;
        if (si) {
            bio_put_string16(reply, si->name);
            return 0;
        }
        return -1;
    }
    default:  return -1; 
    }
    bio_put_uint32(reply, 0);
    return 0;
}

 binder_send_reply()@{ servicemanager / binder.c}
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;
    data.buffer = buffer_to_free;
    data.cmd_reply = BC_REPLY;
    data.txn.target.ptr = 0;
    data.txn.cookie = 0;
    data.txn.code = 0;
    if (status) {
        data.txn.flags = TF_STATUS_CODE;
        data.txn.data_size = sizeof(int);
        data.txn.offsets_size = 0;
        data.txn.data.ptr.buffer = (uintptr_t)&status;
        data.txn.data.ptr.offsets = 0;
    } else {
        data.txn.flags = 0;
        data.txn.data_size = reply->data - reply->data0;
        data.txn.offsets_size = ((char*) reply->offs) - ((char*) reply->offs0);
        data.txn.data.ptr.buffer = (uintptr_t)reply->data0;
        data.txn.data.ptr.offsets = (uintptr_t)reply->offs0;
    }
    binder_write(bs, &data, sizeof(data)); //在binder_loop()已经介绍过会
}
这里需要特别注意的是ServiceManager跟普通Service的不同之处还在于。对于普通XXService,Client获取到一个BpXXService,然后调用它的一个方法,最终通过Binder机制会将数据交给BnXXService的同名方法处理。然而对于ServiceManager,Client获取到一个BpServiceManager,然后调用它的一个方法,如getService,最终通过Binder机制会将数据交给svcmgr_handler()@{ servicemanager / service_manager.c}处理,而不是交给BnServiceManage处理!!!详细参考链接

ServiceManager注册:
  1. 调用binder_open(128*1024)方法打开文件描述符和在当前进程给/dev/binder设备描述符映射一个块空间。
  2. 调用binder_become_context_manager方法注册自己成为Bidner机制的上下文管理者。方法内部通过ioct方法进入到Binder驱动层,发送一条BINDER_SET_CONTEXT_MGR的Binder驱动层协议的报文。
  3. 调用binder_loop方法进入循环,向Binder驱动器协议发送一条BC_ENTER_LOOPER的IPCThreadState层协议报文,使得当前主线程注册成为Binder线程;随后与Binder驱动层交互获得请求数据交给binder_parse()方法处理。
  4. 根据不同的IPCThreadState层协议报文进行不同处理。如得到BR_TRANSACTION的IPCThreadState层协议报文,会将报文数据解析出来交由svcmgr_handler()方法处理,该方法会解析Binder层协议报文类型,如SVC_MGR_ADD_SERVICE则调用自身的do_add_service方法进行处理,方法执行结束后调用binder_write向IPCThreadState层写入一个BC_REPLY协议报文。

下面分析一下获取ServiceManager代理的getDefaultServiceManager方法底层实现。

getDefaultServiceManager方法的实现


getDefaultServiceManager@{binder/IServiceManager.cpp}
    对于一个一般的Service组件,Client首先需要通过Binder驱动程序获得它的一个句柄值,然后才可以根据这个句柄创建一个Binder代理对象(BpBinder),最后再将这个BpBinder转换成一个实现了特定接口的代理对象。ServiceManager句柄值为0,因此获取ServiceManager组件就没有获取BpBinder的过程。
sp<IServiceManager> defaultServiceManager()
{
    if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
    {
        AutoMutex _l(gDefaultServiceManagerLock);
        if (gDefaultServiceManager == NULL) {
            gDefaultServiceManager = interface_cast<IServiceManager>(
                ProcessState::self()->getContextObject(NULL));
        }
    }
    return gDefaultServiceManager;
}

Binder库中定义了一个gDefaultServiceManager全局变量,而且采用了单例的模式进行实现,getDefaultServiceManager方法获得的就是该全局变量。在第一次请求该变量的时候会通过如下的方式获取一个ServiceManager代理。interface_casr<IserviceManager> (ProcessState:self()->getContextObject(NULL));
  1. ProcessState:self()获得的是一个ProcessState(是一个单例模式)
    • 构造器中调用open_driver方法;
      • int fd = open("/dev/binder", O_RDWR); //打开/dev/binder设备描述符,将获取到的文件描述符存储到ProcessState对象中的一个域中
      • result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads); //告知Binder,其最多可以请求15条线程处理进程间通信
    • mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0); //使用mmap将/dev/binder映射进进程的地址空间中,映射大小为1016KB;
  2. ProcessState:self()->getContextObject(NULL)创建一个句柄为0的Binder代理(BpBinder)
    • 直接调用getStrongProxyForHandle(0) //表示要创建的Binder代理对象的句柄为0
      • getStrongProxyForHandle的操作主要有:(方法参数为int32_t handle)
        sp<IBinder> result;
        handle_entry* e = lookupHandleLocked(handle);
        if (e != NULL) {
                IBinder* b = e->binder;
                if (b == NULL || !e->refs->attemptIncWeak(this)) {
                    b = new BpBinder(handle); //创建一个BpBinder,该构造器会调用IPCThreadState::self()->incWeakHandle(handle)方法,创建了一个IPCThreadState对象
                    e->binder = b;
                    if (b) e->refs = b->getWeakRefs();
                    result = b;
                } else {
                    result.force_set(b);
                    e->refs->decWeak(this);
                }
            }
         return result;

  3. interface_casr<IserviceManager> (const sp<IBinder>& obj)利用第二步得到的Binder代理构建一个ServiceManager代理
    • 等价于new BpServiceManager(obj)

getDefaultServiceManager方法调用结束后,我们首先获得一个ProcessState对象——单列模式(该对象有打开了/dev/binder描述符,设备描述符向进程映射了一段地址空间)、通过ProcessState的getContextObject方法获得一个句柄为0的BpBinder对象(该Binder代理构造器中创建了一个IPCThreadState对象——单例模式),最后利用BpBinder创建一个BpServiceManager对象。

getDefaultServiceManager方法让我们获得了一个sp<IServiceManager>对象,之后就可以调用该对象的addService、getService方法添加和获取指定的Service代理了,下面依次介绍这两个方法。

ServerManager——addService

下面方法是用户添加服务的方法
addService@{binder/IServiceManager.cpp}
virtual status_t addService(const String16& name, const sp<IBinder>& service){
        Parcel data, reply;
        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
        data.writeString16(name);
        data.writeStrongBinder(service);
        status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
        return err == NO_ERROR ? reply.readExceptionCode() : err;
}
前面已经介绍Remote方法获取的是一个BpBinder对象,调用BpBinder对象的transact方法将数据和当前BpBinder对应的句柄发送给Binder驱动层处理。数据封装成一个ADD_SERVICE_TRANSACTION的协议报文交给Binder层处理。
BpBinder::transact()@{ binder / BpBinder.cpp}
status_t BpBinder::transact(  uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)  //最后一个参数为0表示同步进程间请求,否则异步;默认为0
{
    if (mAlive) {
        status_t status = IPCThreadState::self()->transact(  mHandle, code, data, reply, flags); 
        if (status == DEAD_OBJECT) mAlive = 0;
        return status;
    }
    return DEAD_OBJECT;
}
Binder层的数据继续包装成一个IPCThreadState层的BC_TRANSACTION协议报文交给IPCThreadState层处理,调用IPCThreadState对象的transact方法
IPCThreadState::transact()@{ binder / IPCThreadState.cpp}
status_t IPCThreadState::transact(int32_t handle,  uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { 
    status_t err = data.errorCheck(); //检查数据知否正确
    flags |= TF_ACCEPT_FDS; //flag设置标志位
    if (err == NO_ERROR) {
        err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL); //note1
      
    }
    if ((flags & TF_ONE_WAY) == 0) { //同步请求
        if (reply) { err = waitForResponse(reply); } 
        else {
            Parcel fakeReply;
            err = waitForResponse(&fakeReply); //等待Service的返回数据
        }
    }
    else { err = waitForResponse(NULL, NULL); } //不等待Service的返回数据
    return err;
}
1、  将BC_TRANSACTION协议报文数据写入到binder_transaction_data结构体中。 再将该对象写入到IPCThreadState中的一个Parcel输出缓冲区中
IPCThreadState::waitForResponse()@{ binder / IPCThreadState.cpp}
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult){
    int32_t cmd;
    int32_t err;
    while (1) {
        if ((err=talkWithDriver()) < NO_ERROR) break; //note1
        err = mIn.errorCheck();
        if (err < NO_ERROR) break;
        if (mIn.dataAvail() == 0) continue;
       
        cmd = mIn.readInt32();  //note2
        switch (cmd) {
        case BR_TRANSACTION_COMPLETE: //note3
            if (!reply && !acquireResult) goto finish;
            break;
       
        case BR_DEAD_REPLY:
            err = DEAD_OBJECT;
            goto finish;
        case BR_FAILED_REPLY:
            err = FAILED_TRANSACTION;
            goto finish;
        case BR_ACQUIRE_RESULT:
            ```````
            goto finish;
       case BR_REPLY: { //note4
                binder_transaction_data tr;
                err = mIn.read(&tr, sizeof(tr));
                if (err != NO_ERROR) goto finish;
                if (reply) { //reply不为空则给它设值
                    if ((tr.flags & TF_STATUS_CODE) == 0) {
                        reply->ipcSetDataReference(
                            reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
                            tr.data_size,
                            reinterpret_cast<const size_t*>(tr.data.ptr.offsets),
                            tr.offsets_size/sizeof(size_t),
                            freeBuffer, this);
                    } .....
                    }
                } else {
                    ......
                    continue;
                }
            }
            goto finish;
        default:
            err = executeCommand(cmd);
            if (err != NO_ERROR) goto finish;
            break;
        }
    }
finish:
    if (err != NO_ERROR) {
        if (acquireResult) *acquireResult = err;
        if (reply) reply->setError(err);
        mLastError = err;
    }
    return err;
}

1、与Binder驱动程序交互,将前面IPCThreadState::transact()方法中向Parcel输出缓冲区中写入的数据传给Binder驱动
2、读取Binder驱动返回的协议报文
3、收到来自Binder驱动器层的BR_TRANSACTION_COMPLETE协议报文,如果 if (!reply && !acquireResult)为真则退出giant方法,否则继续等待下一个协议报文
4、收到来自Binder驱动器层的BR_REPLY:协议报文,读取报文中的数据交给Parcel *reply。随后用户就可以读取其中的数据了
IPCThreadState::talkWithDriver()@{ binder / IPCThreadState.cpp}
status_t IPCThreadState::talkWithDriver(bool doReceive){
    binder_write_read bwr;
    const bool needRead = mIn.dataPosition() >= mIn.dataSize();
    const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;
    bwr.write_size = outAvail;
    bwr.write_buffer = (long unsigned int)mOut.data(); //即将写入到Binder驱动的数据

    if (doReceive && needRead) {
        bwr.read_size = mIn.dataCapacity();
        bwr.read_buffer = (long unsigned int)mIn.data(); //获得Binder驱动返回的数据
    } else {
        bwr.read_size = 0;
        bwr.read_buffer = 0;
    }
    bwr.write_consumed = 0;
    bwr.read_consumed = 0;
    status_t err;
    
    ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) ///note1
    ....
}
1、将获取到的数据封装成一个Binder驱动层的BINDER_WRITE_READ协议报文,交给Binder启动层处理。使用ioctl方法向Binder驱动层传输数据,IPCThreadState的mProcess变量的mDriverFD即/dev/driver文件描述符。

综上addService方法首先将参数String16& name, sp<IBinder>包装成一个Binder层的ADD_SERVICE_TRANSACTION协议报文,传给Binder层处理。之后数据包装成 IPCThreadState层的BC_TRANSACTION协议报文。最后数据又被包装成Binder驱动层的BINDER_WRITE_READ协议报文交给Binder驱动层处理。

ServerManager——getService

getService()@{binder/IServiceManager.cpp}
virtual sp<IBinder> getService(const String16& name) const {
        unsigned n;
        for (n = 0; n < 5; n++){
            sp<IBinder> svc = checkService(name);
            if (svc != NULL) return svc;
            sleep(1);
        }
        return NULL;
}

checkService()@{binder/IServiceManager.cpp}
virtual sp<IBinder> checkService( const String16& name) const{
        Parcel data, reply;
        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
        data.writeString16(name);
        remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
        return reply.readStrongBinder();
}
与addService方法类似,getService方法首先将参数String16& name包装成一个Binder层的CHECK_SERVICE_TRANSACTION协议报文,传给Binder层处理。之后数据包装成 IPCThreadState层的BC_TRANSACTION协议报文。最后数据又被包装成Binder驱动层的BINDER_WRITE_READ协议报文交给Binder驱动层处理。



Service——注册以mediaServer为例)

main()@{ mediaserver / main_mediaserver.cpp}
int main(int argc, char** argv){
    //获得一个ProcessState实例,前面已经介绍过
    sp<ProcessState> proc(ProcessState::self()); 
    //得到一个ServiceManager对象,前面已经介绍过
    sp<IServiceManager> sm = defaultServiceManager(); 
    MediaPlayerService::instantiate();//note1
    ProcessState::self()->startThreadPool();//note2
    IPCThreadState::self()->joinThreadPool();//note3
}
1、MediaPlayerService 实例化,该方法内部为defaultServiceManager()->addService(  String16("media.player"), new MediaPlayerService())方法。service_manager收到addService的请求,然后把对应信息放到自己保存的一个服务list中。具体内容参见前面的addService说明。
2、启动一个Binder线程池
3、将当前主线程添加到这个Binder线程池中去等待和处理Client进程的通信请求。一旦收到一个请求就调用executeCommand去处理这个命令,
startThreadPool()@{ binder / ProcessState.cpp}
void ProcessState::startThreadPool() { 
    AutoMutex _l(mLock);
    if (!mThreadPoolStarted) {
        mThreadPoolStarted = true;
        spawnPooledThread(true);
    }
}
spawnPooledThread()@{ binder / ProcessState.cpp}
void ProcessState::spawnPooledThread(bool isMain) { 
    if (mThreadPoolStarted) {
        int32_t s = android_atomic_add(1, &mThreadPoolSeq);
        char buf[32];
        sprintf(buf, "Binder Thread #%d", s);
        sp<Thread> t = new PoolThread(isMain); //创建PoolThread对象
        t->run(buf); //启动该线程池
    }
}
joinThreadPool()@{ binder / IPCThreadState.cpp}
void IPCThreadState::joinThreadPool(bool isMain) {  //默认参数为ture
    mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER); //note1
    status_t result;
    do {
        int32_t cmd;
        ......
        result = talkWithDriver(); //note2
        if (result >= NO_ERROR) {
            size_t IN = mIn.dataAvail();
            if (IN < sizeof(int32_t)) continue;
            cmd = mIn.readInt32();
            result = executeCommand(cmd); //处理从Binder驱动返回回来的协议数据
        }
        ....
        if(result == TIMED_OUT && !isMain) {
            break;  
        }
    } while (result != -ECONNREFUSED && result != -EBADF);
    mOut.writeInt32(BC_EXIT_LOOPER);
    talkWithDriver(false);
}
1、形成一个BC_ENTER_LOOPER 协议报文,将报文写入mOut的Parcel输出缓冲区中。isMain == true表示进入到Looper,否则为注册到Looper;
2、将mOut缓冲区中的数据传给Binder驱动,上面我们知道这里会将数据包装成一个Binder驱动层的BINDER_WRITE_READ协议报文交给Binder驱动层处理
executeCommand()@{ binder / IPCThreadState.cpp}
status_t IPCThreadState::executeCommand(int32_t cmd)
{
    BBinder* obj;
    RefBase::weakref_type* refs;
    status_t result = NO_ERROR;
    switch (cmd) {
    case BR_ERROR:
        result = mIn.readInt32();
        break;
    case BR_OK: 
        break;
    case BR_ACQUIRE:
        refs = (RefBase::weakref_type*)mIn.readInt32();
        obj = (BBinder*)mIn.readInt32();
        obj->incStrong(mProcess.get());
        mOut.writeInt32(BC_ACQUIRE_DONE);
        mOut.writeInt32((int32_t)refs);
        mOut.writeInt32((int32_t)obj);
        break;
    case BR_RELEASE:
        refs = (RefBase::weakref_type*)mIn.readInt32();
        obj = (BBinder*)mIn.readInt32();
        mPendingStrongDerefs.push(obj);
        break;
    case BR_INCREFS:
        refs = (RefBase::weakref_type*)mIn.readInt32();
        obj = (BBinder*)mIn.readInt32();
        refs->incWeak(mProcess.get());
        mOut.writeInt32(BC_INCREFS_DONE);
        mOut.writeInt32((int32_t)refs);
        mOut.writeInt32((int32_t)obj);
        break;
    case BR_DECREFS:
        refs = (RefBase::weakref_type*)mIn.readInt32();
        obj = (BBinder*)mIn.readInt32();
        mPendingWeakDerefs.push(refs);
        break;
    case BR_ATTEMPT_ACQUIRE:
        refs = (RefBase::weakref_type*)mIn.readInt32();
        obj = (BBinder*)mIn.readInt32();  { 
            const bool success = refs->attemptIncStrong(mProcess.get());
            mOut.writeInt32(BC_ACQUIRE_RESULT);
            mOut.writeInt32((int32_t)success);
        }
        break;
   
    case BR_TRANSACTION:{ 
            binder_transaction_data tr;
            result = mIn.read(&tr, sizeof(tr));
            if (result != NO_ERROR) break;
            Parcel buffer;
            buffer.ipcSetDataReference(
                reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
                tr.data_size,
                reinterpret_cast<const size_t*>(tr.data.ptr.offsets),
                tr.offsets_size/sizeof(size_t), freeBuffer, this);
            const pid_t origPid = mCallingPid;
            const uid_t origUid = mCallingUid;
            mCallingPid = tr.sender_pid;
            mCallingUid = tr.sender_euid;
            mOrigCallingUid = tr.sender_euid;
            int curPrio = getpriority(PRIO_PROCESS, mMyThreadId);
            if (gDisableBackgroundScheduling) {
                if (curPrio > ANDROID_PRIORITY_NORMAL) {
                    setpriority(PRIO_PROCESS, mMyThreadId, ANDROID_PRIORITY_NORMAL);
                }
            } else {
                if (curPrio >= ANDROID_PRIORITY_BACKGROUND) {
                    set_sched_policy(mMyThreadId, SP_BACKGROUND);
                }
            }
            Parcel reply;
            if (tr.target.ptr) {
                sp<BBinder> b((BBinder*)tr.cookie);
                const status_t error = b->transact(tr.code, buffer, &reply, tr.flags); //调用BBinder的transact方法处理,实则底层就是调用具体服务的onTransact方法!
                if (error < NO_ERROR) reply.setError(error);
            } else {
                const status_t error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
                if (error < NO_ERROR) reply.setError(error);
            }
           
            if ((tr.flags & TF_ONE_WAY) == 0) {
                sendReply(reply, 0); //发送一个IPCThreadState层的BC_REPLY协议报文给Binder驱动层
            } else { }
           
            mCallingPid = origPid;
            mCallingUid = origUid;
            mOrigCallingUid = origUid;
        }
        break;
   
    case BR_DEAD_BINDER:
        {
            BpBinder *proxy = (BpBinder*)mIn.readInt32();
            proxy->sendObituary();
            mOut.writeInt32(BC_DEAD_BINDER_DONE);
            mOut.writeInt32((int32_t)proxy);
        } break;
       
    case BR_CLEAR_DEATH_NOTIFICATION_DONE:
        {
            BpBinder *proxy = (BpBinder*)mIn.readInt32();
            proxy->getWeakRefs()->decWeak(proxy);
        } break;
       
    case BR_FINISHED:
        result = TIMED_OUT;
        break;
       
    case BR_NOOP:
        break;
       
    case BR_SPAWN_LOOPER:
        mProcess->spawnPooledThread(false);
        break;
       
    default:
        result = UNKNOWN_ERROR;
        break;
    }
    if (result != NO_ERROR) {
        mLastError = result;
    }
    return result;
}

BBinder::transact()
status_t BBinder::transact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { 
   err = onTransact(code, data, reply, flags); //就是调用自己的onTransact函数嘛      
   return err; 
}
sendReply()@{ binder / IPCThreadState.cpp}
status_t IPCThreadState::sendReply(const Parcel& reply, uint32_t flags)
{
    status_t err;
    status_t statusBuffer;
    err = writeTransactionData(BC_REPLY, flags, -1, 0, reply, &statusBuffer);
    if (err < NO_ERROR) return err;
    return waitForResponse(NULL, NULL);
}
Service注册:
  1. 创建一个ProcessState对象,该对象会打开文件描述符和在当前进程给/dev/binder设备描述符映射一个块空间。
  2. 利用ProcessState的getContextObject(NULL)方法获取一个句柄为0的IBinder对象,该IBinder对象的创建过程中会创建一个IPCThreadState对象。
  3. 利用IBinder对象创建一个IServerManager对象。
  4. 创建一个当前服务的实例,并调用IServerManager的addService方法,将自己注册到ServiceMaanger列表中。addService的过程是一个"Client端通信流程",具体后文还会再讲
  5. 启动一个Binder线程池和并将当前主线程加入到Binder线程池中,最终进入到“Server端通信流程”
Service循环:
   IPCThreadState的joinThreadPool方法开启了一个循环,不断与Binder驱动进行通信,当获取到信息就调用executeCommand( cmd )方法对消息进行处理。比如cmd为BR_TRANSACTION,即表明是Binder发送过来的期望Service处理的数据,首先从得到的数据中得到sp<BBinder>对象,随后调用该对象的transact方法,方法内部会调用BBinder绑定的Service(其实就是当前Service)的onTransact的方法进行处理,处理过后将结果以BC_REPLY协议报文返回Binder,然后调用waitForResponse方法等待Binder返回一个BR_TRANSACTION_COMPLETED协议报文,最后结束这一次的服务。
注意:startThreadPool和joinThreadPool完后确实有两个线程,主线程和工作线程,而且都在做消息循环。为什么要这么做呢?他们参数isMain都是true。不知道google搞什么。难道是怕一个线程工作量太多,所以搞两个线程来工作?这种解释应该也是合理的。网上有人测试过把最后一句屏蔽掉,也能正常工作。但是难道主线程提出了,程序还能不退出吗?这个...管它的,反正知道有两个线程在那处理就行了。


Client景分析以mediaServer为例)

使用MediaPlayerService的时候,先要创建它的BpMediaPlayerService,一个描述了实现IMediePlayService接口的组件。
defaultServiceManager()->getService(String16(MEDIA_SERVICE));该方法在前面的ServiceManager已经介绍过了,获得了一个IBinder对象。之后又利用该IBinder包装成一个IServiceManager对象。当我们调用IServiceManager的一个方法的时候实则调用IBinder的transact方法,首先写入Binder层的协议报文再通过调用IPCThreadState的transact方法处理,IPCThreadState又会将报文加一个文件如BC_TRANSACTION头,通过ioctl发送到Binder驱动程序,Binder将该报文发给对应的服务端的时候就会返回一个BR_TRANSACTION_COMPLETED协议,Client继续等待直到Binder发送BR_REPLY,这时候CLIEN读取该协议的数据返回Client用户空间,这样一次进程间通信就结束了。

总结:

    虽然说这是Binder机制——初探,但是内容一点也不少,不过这真的只是Binder的冰山一角。本文只是在open、mmap、ioctl基础之上对Binder机制进行分析,而对于具体的binder驱动层没有进行介绍。想了解Binder机制还是需要有一个切入点比较好,如果你还很迷茫不知道何从下手,那么个人建议按照ServiceManager的注册、具体Service的注册、Client对Service的访问三个步骤来了解Binder机制。
    而针对上面的三个步骤又可以细分如下
  • ServiceManager注册:binder_open() 、binder_become_context_manager() 、binder_loop(){该部分细分:ioctl()、 ioctl、binder_parse}
  • Service注册:getDefaultServiceManager(){底层实现细分:ProcessState、IPCThreadState、BpBinder、BpServiceManager}、addService(){底层在进程间通信时分析} 、Binder线程池、 IPCThreadState线程注册为Biinder线程并进入循环{该部分细分: talkWithDriver、executeCommand}
  • Client对Service的访问:getDefaultServiceManager()、getService(){底层在进程间通信时分析} 、进程间通信{该部分细分如下: BpBinder.transact()  、IPCThreadState.transact() 、 IPCThreadState.waitForResponse(){ 该部分细分: IPCThreadState.talkWithDriver() 、等待Binder驱动层返回协议报文

附录一:binder驱动层

binder_ioctl@{ android / binder.c}
static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
    int ret;
    struct binder_proc *proc = filp->private_data;
    struct binder_thread *thread;
    unsigned int size = _IOC_SIZE(cmd);
    void __user *ubuf = (void __user *)arg;
    trace_binder_ioctl(cmd, arg);
    ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
    if (ret)
        goto err_unlocked;
    binder_lock(__func__);
    thread = binder_get_thread(proc);
    if (thread == NULL) {
        ret = -ENOMEM;
        goto err;
    }
    switch (cmd) {
    case BINDER_WRITE_READ: {
        struct binder_write_read bwr;
        if (size != sizeof(struct binder_write_read)) {
            ret = -EINVAL;
            goto err;
        }
        if (copy_from_user(&bwr, ubuf, sizeof(bwr))) { //获取用户态的binder_write_read对象
            ret = -EFAULT;
            goto err;
        }
        if (bwr.write_size > 0) {//如果输入缓冲区长度大于0则调用binder_thread_write方法
            ret = binder_thread_write(proc, thread, (void __user *)bwr.write_buffer, bwr.write_size, &bwr.write_consumed); 
            trace_binder_write_done(ret);
            if (ret < 0) {
                bwr.read_consumed = 0;
                if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
                    ret = -EFAULT;
                goto err;
            }
        }
        if (bwr.read_size > 0) {//如果输出缓冲区长度大于0则调用binder_thread_read方法
            ret = binder_thread_read(proc, thread, (void __user *)bwr.read_buffer, bwr.read_size, &bwr.read_consumed, filp->f_flags & O_NONBLOCK);
            trace_binder_read_done(ret);
            if (!list_empty(&proc->todo))
                wake_up_interruptible(&proc->wait);
            if (ret < 0) {
                if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
                    ret = -EFAULT;
                goto err;
            }
        }
        if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
            ret = -EFAULT;
            goto err;
        }
        break;
    }
    case BINDER_SET_MAX_THREADS:
        if (copy_from_user(&proc->max_threads, ubuf, sizeof(proc->max_threads))) {
            ret = -EINVAL;
            goto err;
        }
        break;
    case BINDER_SET_CONTEXT_MGR:
        if (binder_context_mgr_node != NULL) {
            printk(KERN_ERR "binder: BINDER_SET_CONTEXT_MGR already set\n");
            ret = -EBUSY;
            goto err;
        }
        ret = security_binder_set_context_mgr(proc->tsk);
        if (ret < 0)
            goto err;
        if (binder_context_mgr_uid != -1) {
            if (binder_context_mgr_uid != current->cred->euid) {
                printk(KERN_ERR "binder: BINDER_SET_"
                       "CONTEXT_MGR bad uid %d != %d\n",
                       current->cred->euid,
                       binder_context_mgr_uid);
                ret = -EPERM;
                goto err;
            }
        } else
            binder_context_mgr_uid = current->cred->euid;
        binder_context_mgr_node = binder_new_node(proc, NULL, NULL);
        if (binder_context_mgr_node == NULL) {
            ret = -ENOMEM;
            goto err;
        }
        binder_context_mgr_node->local_weak_refs++;
        binder_context_mgr_node->local_strong_refs++;
        binder_context_mgr_node->has_strong_ref = 1;
        binder_context_mgr_node->has_weak_ref = 1;
        break;
    case BINDER_THREAD_EXIT:
        binder_debug(BINDER_DEBUG_THREADS, "binder: %d:%d exit\n",
                 proc->pid, thread->pid);
        binder_free_thread(proc, thread);
        thread = NULL;
        break;
    case BINDER_VERSION:
        if (size != sizeof(struct binder_version)) {
            ret = -EINVAL;
            goto err;
        }
        if (put_user(BINDER_CURRENT_PROTOCOL_VERSION, &((struct binder_version *)ubuf)->protocol_version)) {
            ret = -EINVAL;
            goto err;
        }
        break;
    default:
        ret = -EINVAL;
        goto err;
    }
    ret = 0;
err:
    if (thread)
        thread->looper &= ~BINDER_LOOPER_STATE_NEED_RETURN;
    binder_unlock(__func__);
    wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
    if (ret && ret != -ERESTARTSYS)
        printk(KERN_INFO "binder: %d:%d ioctl %x %lx returned %d\n", proc->pid, current->pid, cmd, arg, ret);
err_unlocked:
    trace_binder_ioctl_done(ret);
    return ret;
}

reference:
【2】http://www.cnblogs.com/innost/archive/2011/01/09/1931456.html(内容比较乱,但是讲的不错)
【3】《Android源码系统情景分析》 罗升阳
【4】《深入理解android 卷I/卷II》 邓凡平
【5】《Android内核剖析》柯元旦 


大话Binder机制

标签:

原文地址:http://blog.csdn.net/evan_man/article/details/51519754

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!