zoukankan      html  css  js  c++  java
  • android binder 基础实例及解析(一)【转】

    本文转载自:http://blog.csdn.net/newchenxf/article/details/49359283#insertcode

    原文网址(转载请注明出处): 
    http://blog.csdn.net/newchenxf/article/details/49359283

    众所周知,binder是android最难啃的骨头,本人深有体会,分析framework的代码很痛苦,搞不清函数到底怎么从一个进程调用到另一个进程。 
    所以,我不得不冷静一下,仔细分析binder到底怎么用,并写了一些sample code,作为实验。

    网上已有各位大神对binder做深入分析,比如 
    【Android深入浅出之Binder机制】 
    http://www.cnblogs.com/innost/archive/2011/01/09/1931456.html 
    【Binder详解】 
    http://blog.csdn.net/yangzhiloveyou/article/details/14043801 
    【Android Binder机制(超级详尽)】 
    http://blog.csdn.net/coding_glacier/article/details/7520199 
    感谢他们的分享。

    本文将提供一个最基础的binder例子,并对应的做分析,慢慢拨开binder的神秘面纱。 
    例子的目录结构。 
    Android.mk 
    client->Android.mk, main_client.cpp) 
    interface->IXXXXService.cpp, IXXXXService.h 
    server->Android.mk, XXXXService.cpp, XXXXService.h, main_XXXXService.cpp

    a) 第一步,定义接口 IXXXXService.h

    首先,要用binder,第一件事就是定义一个接口,把你想要做的事情(API)写在这个接口里。本例就2个,setSomething和getSomething。

    #ifndef IXXXXService_H  
    #define IXXXXService_H 
    
    #include <binder/IInterface.h>
    
    namespace android {
    class IXXXXService : public IInterface {
    public:
        DECLARE_META_INTERFACE(XXXXService);
        virtual int setSomething(int a) = 0;
        virtual int getSomething() = 0;
    };
    
    class BnXXXXService : public BnInterface<IXXXXService> {
    public:
        virtual status_t    onTransact( uint32_t code,
                                        const Parcel& data,
                                        Parcel* reply,
                                        uint32_t flags = 0);
    };
    
    }
    #endif
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    这个文件就写2个东西:IXXXXService和BnXXXXService。

    IXXXXService,这个类必须继承IInterface,然后把你想要的API都写在这个接口里。谁会继承这个接口?有2个,一个是BpXXXXService,一个是BnXXXXService。 
    BnXXXXService。这个必须继承模板类BnInterface。 
    该模板的定义是

    template<typename INTERFACE>
    class BnInterface : public INTERFACE, public BBinder
    • 1
    • 2

    所以呢,相当于BnXXXXService继承了IXXXXService和BBinder。

    奇怪的是,为啥BnInterface 需要把它写在头文件,而BpXXXXService不用呢?因为BpXXXXService对别人是透明的,客户端甚至都不需要知道它的存在。那你就要问了,不知道存在的话,我还怎么new他? 
    其实android给你包好了,当你客户端调用interface_cast(*)时,就会帮你new BpXXXXService。 
    但BnXXXXService就不一样,还有真正的XXXXService必须继承BnXXXXService,从而去实现真正的API函数,所以就必须放在头文件。 
    没看明白没关系,后文会慢慢告诉你具体意思的。

    继续,这个头文件最神秘的是DECLARE_META_INTERFACE,它定义在IInterface.h, 且看其定义。

    #define DECLARE_META_INTERFACE(INTERFACE)                               
        static const android::String16 descriptor;                          
        static android::sp<I##INTERFACE> asInterface(                       
                const android::sp<android::IBinder>& obj);                  
        virtual const android::String16& getInterfaceDescriptor() const;    
        I##INTERFACE();                                                     
        virtual ~I##INTERFACE();                                            
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    所以,相当于头文件加了以下的内容。

        static const android::String16 descriptor;
        static android::sp<IXXXXService> asInterface(
                const android::sp<android::IBinder>& obj);
        virtual const android::String16& getInterfaceDescriptor() const;
        IXXXXService();
        virtual ~IXXXXService();
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    所以,人家接口IXXXXService是很严格的喔,也有构造函数析构函数的。 
    根据定义,我们可以总结,IXXXXService有如下几个函数。 
    setSomething 
    getSomething 
    asInterface 
    getInterfaceDescriptor。 
    还有个静态变量descriptor,这个不管是派生类BpXXXXService还是派生类BnXXXXService,都一样的。

    b) 第二步,IXXXXServie.cpp

    这个文件主要实现BpXXXXService和BnXXXXService

    #include "IXXXXService.h"
    #include <binder/Parcel.h>
    #include <binder/IInterface.h>
    #include <utils/Log.h>
    
    #define LOG_NDEBUG 0
    #define LOG_TAG "chenxf: IXXXXService"
    
    namespace android {
    
    enum {
        SET_SOMETHING = IBinder::FIRST_CALL_TRANSACTION,
        GET_SOMETHING,
    };
    
    //------------------------------------proxy side--------------------------------
    
    class BpXXXXService : public BpInterface<IXXXXService> {
    public:
        BpXXXXService(const sp<IBinder>& impl)
            : BpInterface<IXXXXService>(impl) {
        }
        virtual int setSomething(int a) {
            ALOGD(" BpXXXXService::setSomething a = %d ", a);
            Parcel data,reply;
            data.writeInt32(a);
            remote()->transact(SET_SOMETHING,data,&reply);
            return reply.readInt32();
        }
        virtual int getSomething() {
            ALOGD(" BpXXXXService::getSomething ");
            Parcel data,reply;
            data.writeInterfaceToken(IXXXXService::getInterfaceDescriptor());
            remote()->transact(GET_SOMETHING,data,&reply);
            return reply.readInt32();
        }
    };
    //---------------------- interface--------------------
    IMPLEMENT_META_INTERFACE(XXXXService, "chenxf.binder.IXXXXService");
    
    
    //------------------------------------server side--------------------------------
    status_t BnXXXXService::onTransact (
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){
        switch (code) {
            case SET_SOMETHING: {
                ALOGD("BnXXXXService::onTransact  SET_SOMETHING ");
                reply->writeInt32(setSomething((int) data.readInt32()));
                return NO_ERROR;
            } break;
            case GET_SOMETHING: {
                ALOGD("BnXXXXService::onTransact  GET_SOMETHING ");
                reply->writeInt32(getSomething());
                return NO_ERROR;
            } break;
        }
        return BBinder::onTransact(code, data, reply, flags);
    }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    就像前面的DECLARE_META_INTERFACE一样,这个文件最神秘的就是IMPLEMENT_META_INTERFACE。它其实就是实现了DECLARE_META_INTERFACE定义的虚函数,特别是asInterface! 
    来看一下他的定义(IInterface.h)

    #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       
        const android::String16 I##INTERFACE::descriptor(NAME);             
        const android::String16&                                            
                I##INTERFACE::getInterfaceDescriptor() const {              
            return I##INTERFACE::descriptor;                                
        }                                                                   
        android::sp<I##INTERFACE> I##INTERFACE::asInterface(                
                const android::sp<android::IBinder>& obj)                   
        {                                                                   
            android::sp<I##INTERFACE> intr;                                 
            if (obj != NULL) {                                              
                intr = static_cast<I##INTERFACE*>(                          
                    obj->queryLocalInterface(                               
                            I##INTERFACE::descriptor).get());               
                if (intr == NULL) {                                         
                    intr = new Bp##INTERFACE(obj);                          
                }                                                           
            }                                                               
            return intr;                                                    
        }                                                                   
        I##INTERFACE::I##INTERFACE() { }                                    
        I##INTERFACE::~I##INTERFACE() { }                                   
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    相当于IXXXXService.cpp有如下的具体内容:

        const android::String16 IXXXXService::descriptor("chenxf.binder.IXXXXService");
        const android::String16&
                IXXXXService::getInterfaceDescriptor() const {
            return IXXXXService::descriptor;
        } 
        android::sp<IXXXXService> IXXXXService::asInterface(
                const android::sp<android::IBinder>& obj)
        {
            android::sp<IXXXXService> intr;
            if (obj != NULL) {
                intr = static_cast<IXXXXService>(
                    obj->queryLocalInterface(
                            IXXXXService::descriptor).get()); 
                if (intr == NULL) {
                    intr = new BpXXXXService(obj);
                }
            } 
            return intr;
        }
        IXXXXService::IXXXXService() { }
        IXXXXService::~IXXXXService() { }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    可见,咱接口IXXXXService是有个固定的名号的,那就是“chenxf.binder.IXXXXService”。不管是派生类BpXXXXService还是派生类BnXXXXService,都可以使用这个名号!(用getInterfaceDescriptor函数就行) 
    此外,函数asInterface会实现new BpXXXXService。

    这个文件还实现了BnXXXXService的onTransact函数。这个函数主要就是处理proxy发来的调用。比如proxy发了想要调用服务端的setSomething函数,它发起了 
    remote()->transact(SET_SOMETHING,data,&reply); 
    那么,经过binder驱动,将会回调到onTransact。这个函数只负责把客户的需求处理,比如,如果是SET_SOMETHING,那就执行 
    setSomething((int) data.readInt32()) 
    至于setSomething要做什么,那么就不关BnXXXXService的事了,它还是有虚函数setSomething,所以可以预知肯定有别的派生类要继承并实现它。那就是传说中的XXXXService。

    c) 第三步,XXXXService.h

    这是XXXXService的头文件,主要就是声明XXXXService,继承BnXXXXService。

    #include "../interface/IXXXXService.h"
    #include <binder/BinderService.h>
    
    namespace android {
    class XXXXService : public BinderService<XXXXService>, public BnXXXXService {
    public:
        XXXXService();
        static const char* getServiceName() { return "XXXXService"; }//will be the service name
        virtual int setSomething(int a);
        virtual int getSomething();
    protected:
        int myParam;
      };
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    从头文件可知,XXXXService除了要继承BnXXXXService,还要继承模板类BinderService,这主要是为了让XXXXService成为一个任何进程都可以获取的binder服务程序。 
    既然要继承BinderService,那就要写一个getServiceName函数,其返回值就是该服务注册到ServiceManager的名字。

    d) 第四步,XXXXService.cpp

    这就要具体实现说好的setSomething和getSomething函数了。 
    本例比较简单,调用过来,就加1,如果你有需要,可以做更多事情。

    #include <binder/IPCThreadState.h>
    #include <binder/IServiceManager.h>
    #include <utils/Log.h>
    #include <binder/Parcel.h>
    #include <binder/IPCThreadState.h>
    #include <utils/threads.h>
    
    #include <cutils/properties.h>
    #include "XXXXService.h"
    #define LOG_NDEBUG 0
    #define LOG_TAG "chenxf: XXXXService"
    
    namespace android {
        XXXXService::XXXXService() {
            myParam = 0;
        }
    
        int XXXXService::setSomething(int a) {
            ALOGD(" XXXXService::setSomething a = %d myParam %d", a, myParam);
            myParam += a;
            return 0;//OK
        }
        int XXXXService::getSomething() {
            ALOGD("#XXXXService::getSomething myParam = %d", myParam);
            return myParam;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    完成上面四步,我们做完了binder服务的基本框架 
    1. 一个标准的接口,IXXXXService; 
    代理端的实现BpXXXXService。对他来说,他继承了IXXXXService接口的函数,比如setSomething,但对他来说,实现这个接口主要就是传输调用remote()->transact(….),告诉服务程序有这么一个请求调用。 
    2. 服务端的中间实现BnXXXXService。对他来说,继承了模板类BnInterace,相当于继承了IXXXXService和BBinder,但不去实现IXXXXService的函数,而主要实现BBinder的onTransact函数,用于处理刚才说的remote()->transact(….)。 
    3. 服务端的真正实现XXXXService。他继承了BnXXXXService和BinderService。并且会实现接口的函数,比如setSomething。

    请注意,BpXXXXService实现的setSomething和XXXXService实现的setSomething没有直接关系喔,他们属于不同的进程,而且各自实现该函数。BpXXXXService的setSomething主要是传递个消息,告诉binder驱动,有这么一个事情要办,binder驱动会告诉服务进程,有人找上门了,要setSomething,麻烦XXXXService去做一下。

    d) 第五步,main_XXXXService.cpp

    开始服务进程,启动XXXXService,并注册到ServiceManager,让所有人都可以找到他. 
    既然我们都写好了XXXXService,那总得有人new他吧?那必须的。 
    我们写一个main,起一个新的进程,该进程会new XXXXService,并注册到ServiceManager。

    #include <binder/IPCThreadState.h>
    #include <binder/ProcessState.h>
    #include <binder/IServiceManager.h>
    #include <utils/Log.h>
    
    #include "XXXXService.h"
    #define LOG_NDEBUG 0
    #define LOG_TAG "chenxf: XXXXService-main"
    
    #define EASY_START_BINDER_SERVICE 0
    
    using namespace android;
    
    int main(int argc, char** argv)
    {
    #if EASY_START_BINDER_SERVICE
        XXXXService::publishAndJoinThreadPool();//使用了父类BinderService的函数
    #else
        sp<ProcessState> proc(ProcessState::self());
        sp<IServiceManager> sm(defaultServiceManager());
        sm->addService(String16(XXXXService::getServiceName()), new XXXXService());
        ProcessState::self()->startThreadPool();
        IPCThreadState::self()->joinThreadPool();
    #endif
    
        return 0;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    我干嘛要写EASY_START_BINDER_SERVICE?其实没别的意思,只是发现,BinderService的publishAndJoinThreadPool函数,相当于包含了下面的addService/startThreadPool/joinThreadPool,如果你懒得写太多东西的,直接用这个函数,就完事啦。不信请看其定义。

    //BinderService
        static void publishAndJoinThreadPool(bool allowIsolated = false) {
            publish(allowIsolated);
            joinThreadPool();
        }
    
        static status_t publish(bool allowIsolated = false) {
            sp<IServiceManager> sm(defaultServiceManager());
            return sm->addService(
                    String16(SERVICE::getServiceName()),
                    new SERVICE(), allowIsolated);//SERVICE是模板,对本例来说,就是XXXXService
        }
    
        static void joinThreadPool() {
            sp<ProcessState> ps(ProcessState::self());
            ps->startThreadPool();
            ps->giveThreadPoolName();
            IPCThreadState::self()->joinThreadPool();
        }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    我们还是以传统写法来一步步分析吧。也就是

    5.1) sp proc(ProcessState::self())

    请看定义:

    sp<ProcessState> ProcessState::self()
    {
        Mutex::Autolock _l(gProcessMutex);
        if (gProcess != NULL) {
            return gProcess;
        }
        gProcess = new ProcessState;
        return gProcess;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    new了一个ProcessState,注意注意,gProcess是全局变量,所以,一旦这个进程main_XXXXService第一次调用了self()后,它就初始化了,后面任何地方再调用self(),拿到的也是同一个ProcessState实例,也就是说,一个进程只有一个ProcessState。 
    这个ProcessState干了一个最重要的事情,那就是打开binder驱动。 
    请看其构造函数。

    ProcessState::ProcessState()
        : mDriverFD(open_driver())
        , mVMStart(MAP_FAILED)
        , mManagesContexts(false)
        , mBinderContextCheckFunc(NULL)
        , mBinderContextUserData(NULL)
        , mThreadPoolStarted(false)
        , mThreadPoolSeq(1)
    {
        ......
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    也就是mDriverFD = open_driver()。

    static int open_driver()
    {
        int fd = open("/dev/binder", O_RDWR);
        if (fd >= 0) {
            ......
            size_t maxThreads = 15;
            result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
            if (result == -1) {
                ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
            }
        } else {
            ALOGW("Opening '/dev/binder' failed: %s
    ", strerror(errno));
        }
        return fd;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    该函数很简单,就是打开binder驱动,然后设置当前进程,最多可以有15个线程使用binder。

    5.2) sp sm(defaultServiceManager())

    这个其实没话说啦,就是获得ServiceManager的客户端,其实本进程和ServiceManager通信,也是用binder,一样是client/server模式。

    5.3) sm->addService(String16(XXXXService::getServiceName()), new XXXXService())

    很明显,实例化了XXXXService,并且注册到ServiceManager,名字就是刚才在XXXXService.h强调要写的getServiceName的返回值。本例设置的名字就是“XXXXService”。别的进程要找到它,只要找ServiceManager,告诉ServiceManager需要一个名字叫“XXXXService”的服务员^_^。

    5.4) ProcessState::self()->startThreadPool()

    恩,ProcessState::self()就是全局变量gProcess,刚才第一步已经初始化过啦。 
    所以其实第一步不做,也是可以的,只是咱为了代码清晰,还是写着吧。

    void ProcessState::startThreadPool()
    {
        AutoMutex _l(mLock);
        if (!mThreadPoolStarted) {
            mThreadPoolStarted = true;
            spawnPooledThread(true);
        }
    }
    
    //spawnPooledThread
    void ProcessState::spawnPooledThread(bool isMain)
    {
        if (mThreadPoolStarted) {
            String8 name = makeBinderThreadName();
            ALOGV("Spawning new pooled thread, name=%s
    ", name.string());
            sp<Thread> t = new PoolThread(isMain);
            t->run(name.string());
        }
    }
    //makeBinderThreadName
    String8 ProcessState::makeBinderThreadName() {
        int32_t s = android_atomic_add(1, &mThreadPoolSeq);
        String8 name;
        name.appendFormat("Binder_%X", s);
        return name;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    主要就是调用了spawnPooledThread,该函数又new了一个 PoolThread类(继承了Thread),然后调用run启动了该子线程,名字是Binder_*。 
    这就是为啥,我们看android服务程序的某个服务程序,比如mediaserver,经常可以看到Binder_1等子线程。

    #top -t | grep mediase
      ......
      144   587  2   0% S 147108K  11936K  fg media    Binder_1        /system/bin/mediaserver
    • 1
    • 2
    • 3

    那么,这个子线程会干嘛呢? 
    我们知道,PoolThread继承了Thread,所以当执行run以后,将会threadLoop函数。 
    来看PoolThread的threadLoop函数。

    // define in ProcessState.cpp
    virtual bool threadLoop()
    {
        IPCThreadState::self()->joinThreadPool(mIsMain);
        return false;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    他竟然执行了和第五步一样的内容?!!!!而且这是子线程运行的,而第五步joinThreadPool是主线程执行的。没错,在文章【Android深入浅出之Binder机制】也提到过这件事,2个地方都用了joinThreadPool。其实不影响工作,我特地把第五步的“IPCThreadState::self()->joinThreadPool()”换成“while(1){sleep(1)}”,然后binder服务照样可以用。

    5.5) IPCThreadState::self()->joinThreadPool()

    虽然说上一步也会调用,但我们还是分析一下他吧。 
    首先还是来个self()

    IPCThreadState* IPCThreadState::self()
    {
        if (gHaveTLS) {
    restart:
            const pthread_key_t k = gTLS;
            IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
            if (st) return st;
            return new IPCThreadState;
        }
    
        if (gShutdown) return NULL;
    
        pthread_mutex_lock(&gTLSMutex);
        if (!gHaveTLS) {
            if (pthread_key_create(&gTLS, threadDestructor) != 0) {
                pthread_mutex_unlock(&gTLSMutex);
                return NULL;
            }
            gHaveTLS = true;
        }
        pthread_mutex_unlock(&gTLSMutex);
        goto restart;
    }
    //constructor of IPCThreadState
    IPCThreadState::IPCThreadState()
        : mProcess(ProcessState::self()),
          mMyThreadId(androidGetTid()),
          mStrictModePolicy(0),
          mLastTransactionBinderFlags(0)
    {
        pthread_setspecific(gTLS, this);
        clearCaller();
        mIn.setDataCapacity(256);
        mOut.setDataCapacity(256);
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    好吧,他new了一个IPCThreadState。那IPCThreadState与ProcessState啥关系? 
    简单,看构造函数就知道,IPCThreadState的mProcess就是唯一的ProcessState实例。

    好,继续看joinThreadPool

    void IPCThreadState::joinThreadPool(bool isMain)
    {
        ......
        do {
            processPendingDerefs();
            // now get the next command to be processed, waiting if necessary
            result = getAndExecuteCommand();
            }
    
        } while (result != -ECONNREFUSED && result != -EBADF);
    }
    
    //getAndExecuteCommand
    status_t IPCThreadState::getAndExecuteCommand()
    {
        status_t result;
        int32_t cmd;
    
        result = talkWithDriver();
        if (result >= NO_ERROR) {
            size_t IN = mIn.dataAvail();
            if (IN < sizeof(int32_t)) return result;
            cmd = mIn.readInt32();
            IF_LOG_COMMANDS() {
                alog << "Processing top-level Command: "
                     << getReturnString(cmd) << endl;
            }
            result = executeCommand(cmd);
    
        }
    
        return result;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    可以看到,joinThreadPool就起了个while循环,然后不断的从binder驱动读取数据(talkWithDriver),然后处理(executeCommand)。 
    来看一下这个函数。

    status_t IPCThreadState::executeCommand(int32_t cmd)
    {
        BBinder* obj;
        RefBase::weakref_type* refs;
        status_t result = NO_ERROR;
    
        switch (cmd) {
        case BR_TRANSACTION:
        {
            binder_transaction_data tr;
            result = mIn.read(&tr, sizeof(tr));
            if (tr.target.ptr) {
                 p<BBinder> b((BBinder*)tr.cookie);
                error = b->transact(tr.code, buffer, &reply, tr.flags);
            }
            ......
        }
        return result;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    读取binder来的数据tr(类型为binder_transaction_data ),这数据包含了实际的BBinder对象,然后呢,就调用了 
    BBinder的transact函数。

    status_t BBinder::transact(
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    {
        ......
        err = onTransact(code, data, reply, flags);
        return err;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    调用了onTransact。 
    注意BBinder的onTransact是虚函数,虽然他也实现了onTransact,但真正实现的是派生类XXXXService(继承关系:XXXXService->BnXXXXService->BnInterface->BBinder)。所以呢,最后就调用了XXXXService的onTransact,也就是我们写在IXXXXService的onTransact。绕了半天,终于水落石出啦!

    e) 第六步,main_client.cpp,客户端开始使用binder

    #include <stdio.h>
    #include "../interface/IXXXXService.h"
    
    #define LOG_NDEBUG 0
    #define LOG_TAG "chenxf: Client-main"
    
    using namespace android;
    
    sp<IXXXXService> mXXXXService;
    
    void initXXXXServiceClient() {
        int count = 10;
        if (mXXXXService == 0) {
            sp<IServiceManager> sm = defaultServiceManager();
            sp<IBinder> binder;
            do {
                binder = sm->getService(String16("XXXXService"));
                if (binder != 0)
                break;
                ALOGW("XXXXService not published, waiting...");
                sleep(1); // 1 s
                count++;
            } while (count < 20);
            mXXXXService = interface_cast<IXXXXService>(binder);
        }
    }
    
    int main(int argc, char* argv[]) {
        initXXXXServiceClient();
        if(mXXXXService ==NULL) {
            ALOGW("cannot find XXXXService");
            return 0;
        }
    
        while(1) {
            mXXXXService->setSomething(1);
            sleep(1);
            ALOGD("getSomething %d", mXXXXService->getSomething());
        }
        return 0;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    这个是客户端程序,和前面的处在完全不同的进程喔。 
    首先,要用binder,就得找ServiceManager(sp sm = defaultServiceManager();),告诉他我们需要一个名字为XXXXService的服务员( binder = sm->getService(String16(“XXXXService”));) 
    这2句话看似简单,其实很深奥。

    6.1 sp sm = defaultServiceManager()

    sp<IServiceManager> defaultServiceManager()
    {
        if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
    
        {
            AutoMutex _l(gDefaultServiceManagerLock);
            while (gDefaultServiceManager == NULL) {
                gDefaultServiceManager = interface_cast<IServiceManager>(
                    ProcessState::self()->getContextObject(NULL));
                if (gDefaultServiceManager == NULL)
                    sleep(1);
            }
        }
    
        return gDefaultServiceManager;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    这个函数,最最重要的,莫过于调用了ProcessState::self()!如上文所说,它将会new 一个ProcessState,那就意味着必然会执行open_driver,也就是打开/dev/binder驱动!所以说,客户端也是要打开binder驱动的喔。其实也可以理解,不打开,如何跟别人通信呢?只是android封装的太好了,搞得我们很难发现它打开了。

    6.2) binder = sm->getService(String16(“XXXXService”)

    由于服务端已经做过 
    sm->addService(String16(XXXXService::getServiceName()), new XXXXService()),因此我们很容易就获得了service。 
    那返回的binder是啥?他其实是BpBinder实例。它是ServiceManager返回的,这个具体内容要说,又得说一天,而本文侧重实例,所以这里先给出结论,那就是返回的是一个BpBinder()。

    6.3)mXXXXService = interface_cast(binder)

    interface_cast是啥?他是一个函数模板,且看定义

    //IInterface.h
    template<typename INTERFACE>
    inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
    {
        return INTERFACE::asInterface(obj);
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    所以对于本例,就是

    inline sp<IXXXXService> interface_cast(const sp<IBinder>& obj)
    {
        return IXXXXService::asInterface(obj);
    }
    • 1
    • 2
    • 3
    • 4

    所以 
    mXXXXService = IXXXXService::asInterface(binder)。 
    还记得前文第二步没,在IXXXXService.cpp里,加了个宏IMPLEMENT_META_INTERFACE,该宏实现了asInterface函数。 
    根据其定义,就是 
    mXXXXService = new BpXXXXService(binder)。

    至此,我们终于完成任务了!

    总结

    一个最最基本的binder程序写好了,结构还是很简单的。

    我们来看一下,当客户端发起一个调用setSomething,程序会怎么走。

    程序流程

    首先,咱有2个进程,一个是客户端进程,main_client.cpp,一个是服务端进程,main_XXXXService.cpp。 
    客户端进程: 
    1. 客户端调用mXXXXService->setSomething(1) 
    2. 程序走到BpXXXXService的setSomething函数。

    virtual int setSomething(int a) {
        ALOGD(" BpXXXXService::setSomething a = %d ", a);
        Parcel data,reply;
        data.writeInt32(a);
        remote()->transact(SET_SOMETHING,data,&reply);
        return reply.readInt32();
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    BpXXXXService把函数的参数,打包到Parcel对象,比如本例,就一个int数据,放到Parcel。 
    remote()其实就是BpBinder实例。 
    3. 程序走到BpBinder的transact函数。

    status_t BpBinder::transact(
        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
    {
        // Once a binder has died, it will never come back to life.
        if (mAlive) {
            status_t status = IPCThreadState::self()->transact(
                mHandle, code, data, reply, flags);
            if (status == DEAD_OBJECT) mAlive = 0;
            return status;
        }
    
        return DEAD_OBJECT;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    调用了IPCThreadState::self()->transact函数。 
    每个进程都有一个IPCThreadState实例,对client这个进程也一样。 
    通过他的transact函数,往binder驱动写数据。完事。

    服务端进程: 
    1. 服务端的子线程通过执行executeCommand,不断的从binder驱动读取数据,如果发现是送给自己的,就处理数据,即执行了BBinder::transact,从而执行派生类BnXXXXService的onTransact。 
    2. BnXXXXService的onTransact分析数据,发现有人要调用setSomething(即发送代号是SET_SOMETHING),于是乎,解包Parcel拿出函数参数,调用setSomething,其具体实现在XXXXService。 
    3. XXXXService执行setSomething。完事。

    ProcessState和IPCThreadState

    前文分析ProcessState和IPCThreadState有点乱,所以我这里再总结一下他们的关系。 
    每个进程只有唯一的ProcessState对象。客户端和服务端都有。 
    只要进程调用了defaultServiceManager(),就一定会调用到 
    ProcessState::self(),从而实例化ProcessState。

    ProcessState实例来描述当前进程在binder通信时的binder状态。 
    ProcessState有如下3个主要功能: 
    1. 打开binder驱动。 
    2. 创建一个thread,名字为PoolThread,该线程负责与binder驱动进行通信;这个线程的实现主体是一个IPCThreadState对象。 
    3. 为指定的handle创建一个BpBinder对象,并管理该进程中所有的BpBinder对象。

    那一个进程有几个IPCThreadState对象? 
    理论上至少有一个,那就是ProcessState启动PoolThread线程是创建的。但如果用于还在主进程调用了 
    IPCThreadState::self()->joinThreadPool(); 
    那就有2个对象,因为查看IPCThreadState::self()的定义,就知道他是线程独立的。 
    比如我们的server进程,执行了 
    ProcessState::self()->startThreadPool(); 
    IPCThreadState::self()->joinThreadPool(); 
    那必将有2个IPCThreadState对象。 
    但client进程,主进程或者没有任何子线程调用IPCThreadState::self()->joinThreadPool() 
    因此只有一个IPCThreadState对象。

    其实呢,咱一般就当做一个进程只有一个ProcessState和IPCThreadState吧。

    IPCThreadState中有2个Parcel成员,mIn和mOut,IPCThreadState会不停的查询binder驱动中是否有数据可读,如果有将其读出并保存到mIn,同时不停的检查mOut是否有数据需要向BD发送,如果有,则将其内容写入到binder驱动中,总而言之,binder驱动中读出的数据保存到mIn,待写入到binder驱动中的数据保存在了mOut中。 
    ProcessState中生成的BpBinder实例通过调用IPCThreadState的transact函数来向IPCThreadState的mOut中写入数据,这样的话这个binder IPC过程的client端的调用请求的发送过程就明了了。

    下图给出ProcessState与IPCThreadState在client进程和server进程的存在方式。 
    这里写图片描述
    由图中可知,对于client进程,IPCThreadState是主线程创建的,运行在主线程中。主线程将会调用其transact函数,而如上文所说,transact主要调用talkWithDriver,发送数据到driver,然后获得reply,由waitForResponse处理。 
    可见,对于client进程,并不需要起单独的线程不断的监听数据,毕竟,他只是client。 
    对于server进程,IPCThreadState是子线程PoolThread创建的。(假设咱main_XXXXService.cpp不写IPCThreadState::self()->joinThreadPool())。 
    并且,子线程通过joinThreadPool函数,起一个while循环,不断的talkWithDriver,监听driver数据,有数据后,通过executeCommand处理,如果是有效数据,调用BBinder->transact,进而调用BBidner->onTransact,最后走到派生类BnXXXXService的onTransact。

    client进程与server进程的关系

    说了这么多,总得给一个总框图吧。别人都是一开始给出,我就最后给出吧。^^ 
    这里写图片描述

    测试结果

    程序都写好了,总得能跑对吧,恩,首先启动2个进程: 
    root@sprint:/ # test_binder_server & 
    [1] 2784 
    root@sprint:/ # test_binder_client & 
    [2] 2786

    然后看log 
    root@sprint:/ # logcat -v threadtime

    10-24 06:08:40.711  2786  2786 D chenxf: IXXXXService:  BpXXXXService::setSomething a = 1
    10-24 06:08:40.711  2784  2784 D chenxf: IXXXXService: BnXXXXService::onTransact  SET_SOMETHING
    10-24 06:08:40.711  2784  2784 D chenxf: XXXXService:  XXXXService::setSomething a = 1 myParam 0
    10-24 06:08:41.712  2786  2786 D chenxf: IXXXXService:  BpXXXXService::getSomething
    10-24 06:08:41.712  2784  2785 D chenxf: IXXXXService: BnXXXXService::onTransact  GET_SOMETHING
    10-24 06:08:41.712  2784  2785 D chenxf: XXXXService: #XXXXService::getSomething myParam = 1
    10-24 06:08:41.712  2786  2786 D chenxf: Client-main: getSomething 1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    从log可知,BpXXXXService是活在客户端进程2786,而BnXXXXService和XXXXService是活在服务端进程2784。

    附录

    3个Android.mk一并贴出。 
    Android.mk

    include $(call all-subdir-makefiles)
    • 1

    client/Android.mk

    LOCAL_PATH:= $(call my-dir)
    #LOCAL_CFLAGS_ALL :=-I. -I$(LOCAL_PATH)/..
    
    include $(CLEAR_VARS)
    
    LOCAL_SRC_FILES:= 
            main_client.cpp 
            ../interface/IXXXXService.cpp 
            ../interface/ICallback.cpp 
            Callback.cpp
    
    LOCAL_SHARED_LIBRARIES := 
            libui libcutils libutils libbinder
    
    LOCAL_C_INCLUDES := 
        frameworks/base/include 
        frameworks/native/include 
        $(VENDOR_SDK_INCLUDES)
    
    
    LOCAL_MODULE:= test_binder_client
    LOCAL_MODULE_TAGS := optional
    
    include $(BUILD_EXECUTABLE)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    server/Android.mk

    LOCAL_PATH:= $(call my-dir)
    #LOCAL_CFLAGS_ALL :=-I. -I$(LOCAL_PATH)/..
    
    include $(CLEAR_VARS)
    
    LOCAL_SRC_FILES:= 
            main_XXXXService.cpp 
            XXXXService.cpp 
            ../interface/IXXXXService.cpp 
            ../interface/ICallback.cpp
    
    LOCAL_SHARED_LIBRARIES := 
            libcutils libutils libbinder libdl
    
    LOCAL_C_INCLUDES := 
        frameworks/base/include 
        frameworks/native/include 
        $(VENDOR_SDK_INCLUDES)
    
    
    LOCAL_MODULE:= test_binder_server
    LOCAL_MODULE_TAGS := optional
  • 相关阅读:
    通过SSIS监控远程服务器Windows服务并发送邮件报警!
    通过SSIS监控远程服务器磁盘空间并发送邮件报警!
    Jquery和雅虎的YQL服务实现天气预报功能!
    表字段或表名出现Mysql关键字或保留字导致问题 Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have
    Mybatis对象关系映射 one2one,one2many,many2many
    事务的传播属性及隔离级别 Spring
    正整数的二进制表示中1的个数计算(使用移位或者n&(n-1))
    char类型及ASCII码之间比较
    数据表记录包含表索引和数值(int范围的整数),请对表索引相同的记录进行合并,即将相同索引的数值进行求和运算,输出按照key值升序进行输出
    写出一个程序,接受一个十六进制的数,输出该数值的十进制表示。(多组同时输入 )
  • 原文地址:https://www.cnblogs.com/zzb-Dream-90Time/p/7679995.html
Copyright © 2011-2022 走看看