欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

安卓源码解析:Binder进程间通讯机制(4)-内核空间Binder驱动详解(Binder驱动库 C/C++接口简介)

程序员文章站 2022-04-13 11:30:21
...

目录

  1. Binder进程间通讯机制(1)-简况
  2. Binder进程间通讯机制(2)-内核空间Binder驱动详解(基础数据结构)
  3. Binder进程间通讯机制(3)-内核空间Binder驱动详解(Binder驱动内存管理)
  4. Binder进程间通讯机制(4)-内核空间Binder驱动详解(Binder驱动库 C/C++接口简介)
  5. Binder进程间通讯机制(5)-从ServiceManager的角度分析IPC原理

Binder由Service组件和Client组件组成,两个组件通过Binder内核进行通信,Service组件继承BnInterface,包含BnXXXX开头的所有类,Service组件被称为本地对象对应Binder驱动实体对象,Client组件被称为代理对象对应BInder驱动中的引用对象.中的最终功能的实现是继承了BnXXXX的Service类,数据通过IPCThreadState和ProcessState进行向Binder内核通讯.

Service的结构图如下:

安卓源码解析:Binder进程间通讯机制(4)-内核空间Binder驱动详解(Binder驱动库 C/C++接口简介)

  • BnInterface继承IXXXX以及BBinder
template<typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder
{
public:
    virtual sp<IInterface>      queryLocalInterface(const String16& _descriptor);
    virtual const String16&     getInterfaceDescriptor() const;

protected:
    virtual IBinder*            onAsBinder();
};

INTERFACE 为进程自定义的Service组件接口,Client和Service组件都会继承这个接口,并实现里面的方法.Service组件具体的实现会定义在XXXX类中.Service端除了要实现接口还需要实现一个Binder本地对象BnXXXX.

  • 具体实现类XXXX

比如BServiceManager,里面定义了从ServiceManger中获取Service组件getService,以及Client组件向Service组件注册组件setService的具体实现.

status_t BServiceManager::addService(const String16& name, const sp<IBinder>& service)
{
    AutoMutex _l(mLock);
    LOGI("ServiceManager: addService(%s, %p)\n", String8(name).string(), service.get());
    const ssize_t res = mServices.add(name, service);
    if (res >= NO_ERROR) {
        mChanged.broadcast();
        return NO_ERROR;
    }
    return res;
}
sp<IBinder> BServiceManager::getService(const String16& name) const
{
    AutoMutex _l(mLock);
    ssize_t i = mServices.indexOfKey(name);
    LOGV("ServiceManager: getService(%s) -> %d\n", String8(name).string(), i);
    if (i >= 0) return mServices.valueAt(i);
    return NULL;
}
  • BnXXXX

例如 ServiceManager组件的本地对象BnServiceManager用来定义onTransct方法接收binder传递的指令判断后分发给实现类ServiceManager的两个方法.

status_t BnServiceManager::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch(code) {
        case ADD_SERVICE_TRANSACTION: {
            //添加Service
            CHECK_INTERFACE(IServiceManager, data, reply);
            String16 which = data.readString16();
            sp<IBinder> b = data.readStrongBinder();
            status_t err = addService(which, b);
            reply->writeInt32(err);
            return NO_ERROR;
        } break;
    }
}
};

//虚函数addService 被BServiceManager实现
virtual status_t addService(const String16& name, const sp<IBinder>& service)
{
    ....
} 

BServiceManager的addService

status_t BServiceManager::addService(const String16& name, const sp<IBinder>& service)
{
    AutoMutex _l(mLock);
    LOGI("ServiceManager: addService(%s, %p)\n", String8(name).string(), service.get());
    //将Service组件注册到mService集合中
    const ssize_t res = mServices.add(name, service);
    if (res >= NO_ERROR) {
        mChanged.broadcast();
        return NO_ERROR;
    }
    return res;
}
  • BBinder

BnInterface继承了BBinder,在Service组件中,BBinder定义重要的函数onTransact,当Binder代理对象通过Binder驱动程序向一个Binder本地对象发送一个进程间通讯请求时,Binder驱动会调用transact方法进行请求,调用onTransact方法分发与业务相关的请求.其实onTransact会被BBinder的子类,例如BnServiceManager 进行实现,会调用上面所说的BnServiceManageronTransact方法.

  • BnInterface

template<typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder
{
public:
    virtual sp<IInterface>      queryLocalInterface(const String16& _descriptor);
    virtual const String16&     getInterfaceDescriptor() const;

protected:
    virtual IBinder*            onAsBinder();
};


inline sp<IInterface> BnInterface<INTERFACE>::queryLocalInterface(
        const String16& _descriptor)
{
    if (_descriptor == INTERFACE::descriptor) return this;
    return NULL;
}

BnInterface主要提供queryLocalInterfacegetInterfaceDescriptor,第一个方法主要用来获取BnBinder本地对象,第二个方法用来获取描述这个本地对象的字符串.

  • IPCThreadState
class IPCThreadState
{
public:
    static  IPCThreadState*     self();

            status_t            transact(int32_t handle,
                                         uint32_t code, const Parcel& data,
                                         Parcel* reply, uint32_t flags);

private:
    const   sp<ProcessState>    mProcess;
};

}; // namespace android

IPCThreadState是用来和Binder程序进程交互的,每一个Binder线程内部都有一个IPCThreadState,可以根据函数self()获取这个对象,transact是用来和Binder进程交互的函数,与Binder进程交互又是通过调用私有函数talkWithDriver实现,他一方面负责发送给Binder驱动数据一方面用来接收Binder驱动发送过来的数据.

  • ProcessState

每个BInder线程对应的IPCThreadState内部都有一个mProcess成员变量对应的ProcessState对象,他负责初始化Binder设备,负责打开设备文件/dev/binder,并将它映射到进程的地址空间,让每一个BInder线程和Binder驱动建立连接.


Client的结构图如下:

安卓源码解析:Binder进程间通讯机制(4)-内核空间Binder驱动详解(Binder驱动库 C/C++接口简介)

  • BpXXXX

BpXXXX为Binder代理对象的具体实现类,与Binder本地对象继承同一个`IInterface,实现同样的接口,例如在BpServiceManager`中实现了getService以及addService虚函数,当有其他进程要调用ServiceManager的时候会先获取到SM的Binder代理对象并调用他的具体方法.

//代理對象addService
    virtual status_t addService(const String16& name, const sp<IBinder>& service)
    {
        Parcel data, reply;
        //写入协议头(请求头)
        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
        data.writeString16(name);
        //将要传递的Service组件封装成binder结构体
        data.writeStrongBinder(service);
        //调用BpBinder 的 transact方法
        status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
        return err == NO_ERROR ? reply.readExceptionCode() : err;
    }
  • BpRefBase

BpRefBase用来为Binder代理对象提供进程间通讯的抽象接口,其中成员变量mRemote指向一个BpBinder对象,可以通过方法remote()获取.

class BpRefBase : public virtual RefBase
{
protected:
    inline  IBinder*        remote()                { return mRemote; }
    inline  IBinder*        remote() const          { return mRemote; }

private:
    IBinder* const          mRemote;
};

}; // namespace android
  • BpBinder

BpBinder为Binder代理对象实现的进程间通讯接口,成员变量mHandle是一个表示Client组件的句柄,每一个Client组件在Binder驱动中都对应一个Binder引用对象,每一个Binder引用对象都有一个句柄值,client组件就是通过这个句柄值来和binder驱动中的binder引用对象建立联系.

BpBinder的transact方法用来向service组件发送进程间通讯请求,client端会通过这个方法将句柄值发送给Binder驱动,这样binder驱动就能跟着这个句柄找到binder引用对象,继而找到binder实体对象,并将请求发送给binder实体对象所对应的service组件.

而BpBinder具体如何发送指令又是通过IPCThreadState处理的.

相关标签: Binder IPC