Chinaunix首页 | 论坛 | 博客
  • 博客访问: 991
  • 博文数量: 1
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 15
  • 用 户 组: 普通用户
  • 注册时间: 2019-06-26 14:38
文章分类
文章存档

2019年(1)

我的朋友
最近访客

分类: 嵌入式

2019-07-10 20:03:57

接触过android的人都知道Binder服务调用是android系统的基础。它担负是跨进程或进程内调用和数据传递的任务。理解它是理解android众多services的基础。binder服务的层次图如下:

从图中看出,一个binder服务基本分为3层:第一层业务层,它是服务的主体;第二层是粘合层,它把服务的主体和下层的binder层粘合在一起,在这一层上,可以进行transact()调用;第三层是binder层,它负责与binder驱动交互,完成跨进程数据传递。下面从服务端实现说起:

Binder服务的C++实现分析
BnXXXService是由模板类BnInterface生成的,BnInterface扮演粘合剂的角色,它把服务主体接口(IXXXService)和服务载体(BBinder)粘和在一起。它定义在frameworks/base/include/binder/IInterface.h:
  1. template<typename INTERFACE>
  2. class BnInterface : public INTERFACE, public BBinder
  3. {
  4. public:
  5.     virtual sp<IInterface> queryLocalInterface(const String16& _descriptor);
  6.     virtual const String16& getInterfaceDescriptor() const;

  7. protected:
  8.     virtual IBinder* onAsBinder();
  9. };

一个新的服务实体类BnXXXService一般用下面的方式定义:

  1. class BnXXXService : public BnInterface<IXXXService>
  2. {
  3. public:
  4.     virtual status_t onTransact( uint32_t code,
  5.                                     const Parcel& data,
  6.                                     Parcel* reply,
  7.                                     uint32_t flags = 0);
  8. };

模板展开后,相当于:
  1. class BnXXXService : public IXXXService, public BBinder{
  2. public:
  3.     virtual status_t onTransact( uint32_t code,
  4.                                     const Parcel& data,
  5.                                     Parcel* reply,
  6.                                     uint32_t flags = 0);
  7. }
这样BnXXXService同时继承于IXXXService和BBinder。IXXXService是服务的接口,具体的服务函数在BnXXXService中实现。必须重载BnXXXService::onTransact(),在其中对不同的请求code,调用不同的函数。BBinder是服务的载体。当客户端发起服务请求,binder驱动找出相应服务的binder对象,这个binder对象就是BBinder,返回给IPCThreadState,IPCThreadState调用BBinder::transact(),如下面1028行代码所示:
  1. 891 status_t IPCThreadState::executeCommand(int32_t cmd){
  2. ...
  3. 897 switch (cmd) {
  4. ....
  5. 970 case BR_TRANSACTION:
  6. 971 {
  7. 972     binder_transaction_data tr;
  8. 973     result = mIn.read(&tr, sizeof(tr));
  9.         ....
  10. 1026    if (tr.target.ptr) {
  11. 1027        sp<BBinder> b((BBinder*)tr.cookie);
  12. 1028        const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);
  13. 1029        if (error < NO_ERROR) reply.setError(error);
  14. 1030
  15. 1031     } else {
  16.             ....
  17. 1034 }
  18. }

1028行调用BBinder::tranact()。BBinder::tranact()是:

  1. 96 status_t BBinder::transact(
  2. 97 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
  3. 98 {
  4. 99     data.setDataPosition(0);
  5. 100
  6. 101     status_t err = NO_ERROR;
  7. 102     switch (code) {
  8.         ....
  9. 106     default:
  10. 107         err = onTransact(code, data, reply, flags);
  11. 108         break;
  12. 109     }
  13.         ....
  14. 115     return err;
  15. 116 }

107行调用的onTransact(),其实就是BnXXXService::onTransact()。这样就可以在BnXXXService::onTransact()中通过switch语句完成各种各样的服务。有关类的关系如图:


由此看出:BnXXXService包含两部分:一是IXXXService,服务的主体的接口;另一部分是BBinder,它是服务的载体,它和binder驱动共同工作,保证客户的请求最终是对一个binder对象(BBinder类)的调用。从binder驱动的角度,每一个服务就是一个BBinder类,binder驱动负责找出服务对应的BBinder类。然后把这个BBinder类返回给IPCThreadState,IPCThreadState调用BBinder的transact()。BBinder的transact()又会调用onTransact()。BBinder::onTransact()是虚函数,所以实际实际是调用BnXXXService::onTransact(),这样就可在BnXXXService::onTransact()中完成具体的服务函数的调用。

BnXXXService可以用下面的方法以名字“xxx.xxx.serviceName”向ServiceManager注册:
  1. defaultServiceManager()->addService(String16("xxx.xxx.serviceName"), new BnXXXService());

注册后,系统中的其他用户就可以调用这个服务啦。

Binder客户端C++实现分析

如果说BnInterface是服务端服务主体和载体的粘和剂,那么BpInterface就是客户端代理和binder载体的粘合剂。它的定义:
  1. template<typename INTERFACE>
  2. class BpInterface : public INTERFACE, public BpRefBase
  3. {
  4. public:
  5.     BpInterface(const sp<IBinder>& remote);
  6. protected:
  7.     virtual IBinder* onAsBinder();
  8. };

与服务端类似,客服端一般也用下面的方式得到客户端的服务代理:
  1. class BpXXXService: public BpInterface<IXXXService>{
  2. }

这样BpXXXService实际上是
  1. class BpXXXService : public IXXXService, public BpRefBase{
  2. public:
  3.     BpXXXService(const sp<IBinder& remote);
  4. ....
  5. };

构造BpXXXService时需要一个IBinder引用。这个引用从哪里来呢?下面这段代码说明这个问题,它的功能是从ServiceManager得到注册服务代理对象:
  1.     sp<IServiceManager> sm = defaultServiceManager();
  2.     sp<IBinder> binder = sm->getService(String16("IXXXService.name"));
  3.     sp<IXXXService> cs = interface_cast<IXXXService>(binder);

如代码所示:先通过defaultServiceManager()得到IServiceManager的客户代理,然后这个IServiceManager对象查询"IXXXService.name"服务,ServiceManager::getService()返回对应服务的IBinder。最后,interface_cast把这个IBinder转换成服务的客户端代理类BpXXXService。interface_cast的定义如下,

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

  #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::asInterface(                \
            const android::sp& obj)                   \
    {                                                                   \
        android::sp intr;                                 \
        if (obj != NULL) {                                              \
            intr = static_cast(                          \
                obj->queryLocalInterface(                               \
                        I##INTERFACE::descriptor).get());               \
            if (intr == NULL) {                                         \
                intr = new Bp##INTERFACE(obj);                          \
            }                                                           \
        }                                                               \
        return intr;                                                    \
    }                                                                   \
    I##INTERFACE::I##INTERFACE() { }                                    \
    I##INTERFACE::~I##INTERFACE() { }                                   \

关键在:如果obj是BBinder,obj->queryLocalInterface()返回接口本身;如果是BpBinder,则返回NULL。利用这个特性,当queryLocalInterface()返回NULL时,程序构造一个BpXXXService。这就是interface_cast(const sp& obj)返回的客户端代理类BpXXXService。

这里有个细节,binder驱动实际上返回的是服务的句柄(handle),而getService返回的是IBinder。这中间发生了什么?看看getService(),getSerivice()调用checkService():
  1. virtual sp<IBinder> checkService( const String16& name) const
  2. {
  3.     Parcel data, reply;
  4.     data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
  5.     data.writeString16(name);
  6.     remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
  7.     return reply.readStrongBinder();
  8. }
CHECK_SERVICE_TRANSACTION的结果放在reply,binder驱动返回的服务句柄放在reply中,它应该在Parcel::readStrongBinder()中被转换成sp。看看Parcel::readStrongBinder()
  1. sp<IBinder> Parcel::readStrongBinder() const
  2. {
  3.     sp<IBinder> val;
  4.     unflatten_binder(ProcessState::self(), *this, &val);
  5.     return val;
  6. }
  7. ...
  8. status_t unflatten_binder(const sp<ProcessState>& proc,
  9.     const Parcel& in, sp<IBinder>* out)
  10. {
  11.     const flat_binder_object* flat = in.readObject(false);
  12.     
  13.     if (flat) {
  14.         switch (flat->type) {
  15.             case BINDER_TYPE_BINDER:
  16.                 *out = static_cast<IBinder*>(flat->cookie);
  17.                 return finish_unflatten_binder(NULL, *flat, in);
  18.             case BINDER_TYPE_HANDLE:
  19.                 *out = proc->getStrongProxyForHandle(flat->handle);
  20.                 return finish_unflatten_binder(
  21.                     static_cast<BpBinder*>(out->get()), *flat, in);
  22.         }
  23.     }
  24.     return BAD_TYPE;
  25. }
Parcel::readStrongBinder()调unflatten_binder()。在unflatten_binder()里,由于binder驱动返回的是handle,所以ProcessState::getStrongProxyForHandle()被调用。
  1. sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
  2. {
  3.     sp<IBinder> result;

  4.     AutoMutex _l(mLock);

  5.     handle_entry* e = lookupHandleLocked(handle);

  6.     if (e != NULL) {
  7.         IBinder* b = e->binder;
  8.         if (b == NULL || !e->refs->attemptIncWeak(this)) {
  9.             b = new BpBinder(handle); /*以handle为参数构造BpBinder*/ e->binder = b;
  10.             if (b) e->refs = b->getWeakRefs();
  11.             result = b;
  12.         } else {
  13.             ....
  14.         }
  15.     }
  16.     return result;
  17. }
如果应用是第一次请求服务,那lookupHandleLocked(handle)应该返回Null 。这样ProcessState::getStrongProxyForHandle()构造一个以handle为参数构造BpBinder。这个BpBinder就是getService()得到IBinder。这样这个至关重要的handle被保存在BpBinder里。这个BpBinder也是interface_cast(const sp& obj)中输入参数的IBinder。
客户端涉及的类关系图:

到此为止,我们大致勾画出binder调用的过程,服务端用BnInterface模板,把具体服务的接口和BBinder结合起来生成一个服务类。然后把这个服务类向ServiceManager注册,注册简单地说就是把一个服务的名字和它对应的BBinder的句柄(handle)在ServiceManager中关联起来。以后有人需要这个服务,可以用名字得到它的句柄,用这个句柄,binder驱动就可以找到具体的BBinder服务类了。
客户端用BpInterface模板,把具体服务的接口和BpBinder结合起来生成一个客户端代理类。客户端代理类的实质就是一个服务句柄,这个句柄从binder驱动中返回给应用层,应用层再用Parcel::readStrongBinder()把它转换成sp,并把它保存在BpBinder。


阅读(705) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:没有了

给主人留下些什么吧!~~
评论热议
请登录后评论。

登录 注册