Binder概述

Binder是一种Android实现的IPC,用于进程间通信。

通常Linux系统提供好几种进程间通信的方式,比如
1) Message Queue :把进程之间通信用的message保存到内核中或者从内核中读取的方式。

2) Shared Memory:进程间指定共享的内存,把需要传输的内容保存到相应的内存的方式

3) Socket:

Android中选择Binder为主要的IPC方式,因为Binder比其他的IPC方式有更加简洁快速,消耗内存更小等优点。

下面来看一下Framework层Java空间都是怎么用Binder实现进程间通信的。

Framework层Binder

Binder实际是一种C/S模式的工作方式,客户端通过Binde向服务端发出请求,服务端再通过Binder返回相应的内容给服务端。Binder的工作流程如下:
1)客户首先获得服务端的代理对象。所谓代理对象就是客户端建立一个服务端的”引用”,该代理对象具有服务端的功能,使其在客户端访问服务端的方法就像访问本地方法一样。
2)客户端通过调用服务器代理对象的方法,向服务器端发送请求
3)代理对象通过Binder驱动将用户请求发送给服务器端
4)服务器端处理客户端请求,并通过Binder驱动将处理结果返回给客户端
5)客户端收到服务器端的返回结果

这里说的服务端为:BBinder 服务端代理对象为:BpBinder
还需要说一下IBinder接口。这个接口是对跨进程对象的抽象,在C/C++和Java都有定义。IBinder定义了一套使用Binder机制来实现客户程序与服务器的通信协议。
一个对象只能在当前进程中被访问,如果希望它能被其他进程访问,就必须实现IBinder接口。IBinder接口可以指向本地对象,也可以指向远程对象。关键在与IBinder接口中的transact函数。如果IBinder指向服务端代理,那transact负责把请求发送给服务器;如果IBinder指向的是一个服务端,那么transact只负责提供服务。因此不管是服务端还是服务端代理对象,都必须实现该接口,这样才能进行Binder通信。
C/C++中BBinder和BpBinder都是继承了IBinder接口的类。

所以实现Binder就很简单,服务器端继承BBinder并实现onTransact函数,客户端继承BpBinder实现transact函数即可。
以MediaPlayerService为例,在Stagefright.cpp文件的main函数中有如下代码

        sp<IServiceManager> sm = defaultServiceManager();        sp<IBinder> binder = sm->getService(String16("media.player"));        sp<IMediaPlayerService> service =            interface_cast<IMediaPlayerService>(binder);        sp<IOMX> omx = service->getOMX();

这里getOMX函数是BpMediaPlayerService类中的函数,这个很容易看的出来。
定义如下:

    virtual sp<IOMX> getOMX() {        Parcel data, reply;        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());        remote()->transact(GET_OMX, data, &reply); //调用tranact函数发送Binder请求        return interface_cast<IOMX>(reply.readStrongBinder());    }

上述的Binder请求会最终发给服务器端,也就是BnMediaPlayerService类的onTransact函数中

status_t BnMediaPlayerService::onTransact(    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags){    switch (code) {        ...        case GET_OMX: {            CHECK_INTERFACE(IMediaPlayerService, data, reply);            sp<IOMX> omx = getOMX();            reply->writeStrongBinder(omx->asBinder());            return NO_ERROR;        } break;        ...    }}

最终getOMX函数就是调用继承了BnMediaPlayerService类的MediaPlayerService类中的getOMX函数

sp<IOMX> MediaPlayerService::getOMX() {    Mutex::Autolock autoLock(mLock);    if (mOMX.get() == NULL) {        mOMX = new OMX;    }    return mOMX;}

下面来看一下上述的过程是怎么通过Binder驱动来传递的,因为上面说的内容都没有涉及到打开,读写Binder驱动(/dev/binder)的内容。

要看service是怎么打开Binder驱动并实现,必须要从其初始化过程以及service的注册过程看起。
在系统开机的时候,init.rc里边有如下配置,负责启动mediaserver。

service media /system/bin/mediaserver    class main    user media    group system audio camera inet net_bt net_bt_admin net_bw_acct drmrpc sdcard_r shell mediadrm media_rw qcom_diag radio    ioprio rt 4

可以从Android.mk配置中找到,上面的service启动,入口函数是main_mediaserver.cpp文件中的main函数。

int main(int argc __unused, char** argv){    signal(SIGPIPE, SIG_IGN);    char value[PROPERTY_VALUE_MAX];    bool doLog = (property_get("ro.test_harness", value, "0") > 0) && (atoi(value) == 1);    pid_t childPid;    if (doLog && (childPid = fork()) != 0) {        //如果doLog为true,其父进程就会跑到这里,处理几个子进程的消息。这个不是重点,跳过!!    } else {        ...        sp<ProcessState> proc(ProcessState::self());        sp<IServiceManager> sm = defaultServiceManager();        ...        waitBeforeAdding(String16("media.player"));        MediaPlayerService::instantiate();        ALOGI("Add MediaPlayerService on mediaserver");  // SEC_PRODUCT_FEATURE_AUDIO_COMMON        ...        ProcessState::self()->startThreadPool();        IPCThreadState::self()->joinThreadPool();    }}

来看一下上面几行代码的说明

1.  sp<ProcessState> proc(ProcessState::self())     ProcessState没有初始化就初始化,已经初始化的话就把ProcessState的对象加一个sp。这里加sp的作用,    可以看Android中sp/wp的说明,这里就不再赘述。那ProcessState初始化都在干什么呢?    ProcessState::ProcessState()        : mDriverFD(open_driver()) //这里打开Binder驱动设备        , mVMStart(MAP_FAILED)        , mManagesContexts(false)        , mBinderContextCheckFunc(NULL)        , mBinderContextUserData(NULL)        , mThreadPoolStarted(false)        , mThreadPoolSeq(1)    {        if (mDriverFD >= 0) {            //驱动设备的mmap!!!            mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);        }        LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating.");    }2.  sp<IServiceManager> 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;    }    sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)    {        ...        b = new BpBinder(handle);         //BpBinder为一个服务器代理客户端,handle(也就是mHandle)标识一个service。        //一个客户端在通过transact发送Binder消息给ServiceManager的时候会发送自己的handle。        //ServiceManager会根据这个handle来分发Binder消息给相应的服务端。        //handle为0是ServiceManager本身        //当然getService()找到相应的service不是通过handle,而是通过service名字        ...        result = b;    }    BpBinder强制转换成IServiceManager??3.  MediaPlayerService::instantiate()    void MediaPlayerService::instantiate() {        defaultServiceManager()->addService( //                String16("media.player"), new MediaPlayerService());    }    BpServiceManager::addService(){        Parcel data, reply;        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());        data.writeString16(name);        data.writeStrongBinder(service);        data.writeInt32(allowIsolated ? 1 : 0);        status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);        //按理说应该是BnServiceManager::onTransact()函数接收!!!但其实是        //service_manager.c文件的函数接收处理        return err == NO_ERROR ? reply.readExceptionCode() : err;    }    这里的remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply)按理说应该是传到    BnServiceManager::onTransact()函数来处理。但ServiceManager比较特殊。其实这个是传到    service_manager.c文件中去实现了    添加service的操作!!BnServiceManager为什么没有用呢??

4.ProcessState::self()->startThreadPool(), IPCThreadState::self()->joinThreadPool()

把相关的Server加到ServiceManger之后,Service会使用ProcessState::self()->startThreadPool()
启动一个线程(使用IPCThreadState::self()->joinThreadPool()),负责打开Binder驱动等待客户端发来消
息。下面的IPCThreadState::self()->joinThreadPool()本身也会打开一个Binder设备等待客户端消息。

看一下客户端发送Binder消息给对应的Service的流程以及Service接收到Binder消息之后的处理

1.在需要使用到Service完成功能的时候,需要按如下流程发送Binder消息

    1) 需要从ServiceManager根据Service的名字,获取相应的Service(当然如果Service没有注册的话是获取不到    的)。    sp<IServiceManager> sm = defaultServiceManager();    sp<IBinder> binder = sm->getService(String16("media.player"));    mOMX = service->getOMX();    2)打包数据只会通过remote()->transact发送数据    virtual sp<IOMX> getOMX() {        Parcel data, reply;        data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());        remote()->transact(GET_OMX, data, &reply);        return interface_cast<IOMX>(reply.readStrongBinder());    }

2.具体看一下用来发送的am->transact()函数都在干什么

    //am->transact()最终会调用到其父类的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;    }    IPCThreadState::transact() {        IPCThreadState::writeTransactionData();        //负责数据的打包         /* //这里的cookie和handle负责找到指定的Service并调用相应的onTransact函数 //怎么通过cookie或者handle找到相应的onTranact函数呢???? tr.target.ptr = 0; tr.target.handle = handle; tr.code = code; tr.flags = binderFlags; tr.cookie = 0; tr.sender_pid = 0; tr.sender_euid = 0; */        IPCThreadState::waitForResponse();//talkWithDriver()发送Binder消息    }

3.以main_mediaserver.cpp文件为例,main函数最后会通过ProcessState::self()->startThreadPool(), IPCThreadState::self()->joinThreadPool()函数开启线程和打开Binder设备等待客户端发来消息

//来看一下调用流程IPCThreadState::joinThreadPool()->IPCThreadState::getAndExecuteCommand() {     talkWithDriver();     executeCommand(cmd);}executeCommand()//这个函数如果发现是有Binder Transact会跑到下面部分{    if (tr.target.ptr) {        sp<BBinder> b((BBinder*)tr.cookie);        error = b->transact(tr.code, buffer, &reply, tr.flags);    }}//这里tr.target.pr其实就是tr.target.handle。这里b->transact()会调用到//BBinder::transact()->onTransact()然后怎么调用到子类的onTransact()函数的?????/*if(tr.target.ptr)为真的分支部分是最重要的。它从binder内核驱动中获取到一个地址并转换为BBinder类型的指针(该指针在执行IServiceManager::addService()函数时放入binder内核驱动)。记住,MediaPlayerService继承自BnMediaPlayerService,BnMediaPlayerService又继承自BBinder。该指针实际上与BnMediaPlayerService实例是同一个指针。于是接下来的transact()函数将调用到BnMediaPlayerService::onTransact()/

Service的注册以及获取Servcie,然后客户端发送请求给服务端的流程如下:
1) Service启动的时候通过IServiceManager的addService()把自己加到ServiceManager中
2) addService的service参数会在Binder Driver中变成handle变量
3) Binder Driver会根据名字来管理所有的service
4) IServiceManager可以通过getService()找到已经注册的Service的Interface handle
5) android.os.IBinder.INTERFACE_TRANSACTION code来找到Interface handle的实际名字

到此上面解释完了Framework层是怎么通过Binder实现IPC了!!

http://egloos.zum.com/windom/v/1865390

Java Binder

Binder in java layer

Java层的binder机制主要涉及到以下类: 服务层:IFooService;FooService; FooManager其中,IFooService 接口定义服务所提供的方法,由.aidl文件实现;FooService具体实现各个功能函数,提供具体服务;FooManager用于注册和查找该服务;中间层:IFooService.Stub;IFooService.Stub.Proxy中间代码,用于实现框架封装,实际工作中由.aidl接口文件自动生成;IPC层:Binder;BinderProxy;ParcelBinderProxy为Binder对象在本地的代理,接收客户端传过来的数据,对其进行封装,调用JNI函数将数据发送至底层框架;Binder接收从底层框架传过来的数据,解包,并传送至远程服务。Parcel类对数据进行包封装。

Java 层 Binder 框架数据传递的实现

int register_android_os_Binder(JNIEnv* env){    if (int_register_android_os_Binder(env) < 0)        return -1;    if (int_register_android_os_BinderInternal(env) < 0)        return -1;    if (int_register_android_os_BinderProxy(env) < 0)        return -1;    if (int_register_android_os_Parcel(env) < 0)        return -1;    return 0;}

http://www.oss.kr/index.php?mid=oss_repository14&listStyle=list&page=5&document_srl=70352&sort_index=regdate&order_type=desc

Linux Binder驱动

#binder驱动
http://blog.csdn.net/woaieillen/article/details/8455797

待续。。

更多相关文章

  1. android switch模块
  2. Android服务注册完整过程源码分析
  3. Android(安卓)HAL模块实现
  4. Android操作HTTP实现与服务器通信
  5. [Android]解决Fragment无法使用android:onClick属性
  6. Android的View和ViewGroup分析
  7. Android应用程序请求SurfaceFlinger服务渲染Surface的过程分析
  8. Android(安卓)PinyinIME 源码笔记 -- 1. 底层服务接口简介
  9. 箭头函数的基础使用

随机推荐

  1. Android(安卓)操作系统的内存回收机制
  2. Android(安卓)Activity的setTitle,AlertD
  3. Android(安卓)API之Typeface代码演示
  4. Android(安卓)学习笔记——利用JNI技术在
  5. Android(安卓)无线接口层RIL(Radio Layer
  6. Andriod编程基础(一):Andriod的优势及光明
  7. Android(安卓)APK文件在电脑上面运行方法
  8. Android移动图片
  9. Android应用程序注册广播接收器(registerR
  10. 将tensorflow训练好的模型移植到android