您的位置: 首页 > 文章 > Android-Camera Client/Server的binder IPC机制 Android-Camera Client/Server的binder IPC机制 分类: 文章 • 2024-09-17 13:07:16 Android—Camera Client/Server的binder IPC机制 本文首先参考Android Binder IPC分析一文分析了Android Binder IPC通信机制过程及涉及到的各个子元素相关概念,从代码细节脱离出来,因而整体上把握Android binder IPC通信机制,是能够理解文章最后Camera Framework进程间通信实现的基础。参考Android 4.4版本源码。 Binder通信概述 Android进程间通信(Inter-Process Communication, IPC)采用binder通信机制,是一种client/server结构。一个典型的binder单工通信过程如下述示意图。 其基本点为: 1. 表面上看client通过获得一个server的代理接口,对server进行调用。 2. 代理接口中定义的方法与server中定义的方法时一一对应的。 3. client调用某个代理接口中的方法时,代理接口的方法会将client传递的参数打包成Parcel对象。 4. 代理接口将Parcel发送给内核中的binder driver。 5. server会读取binder driver中的请求数据,如果是发送给自己的,解包Parcel对象,处理并将结果返回。 6. 整个的调用过程是一个同步过程,在server处理的时候,client会block住。 ServiceManager ServiceManager(SM)是service的管理器,任何service在被使用之前,均要向SM注册,客户端需要访问某个service时,应该首先向SM查询是否存在该服务。如果SM存在这个service,那么会将该service的handle返回给client,handle是每个service的唯一标识符。 SM的入口函数int main(int argc, char **argv) 在service_manager.c中,进程主要工作为: 1. 初始化binder,打开/dev/binder设备,在内存中为binder映射128k字节空间; 2. 指定SM对应的代理binder的handle为0,当client尝试与SM通信时,需要创建一个handle为0的代理binder; 3. 通知binder driver(BD)使SM成为BD的context manager; 4. 维护一个死循环,在这个死循环中,不停地去读内核中binder driver,查看是否有可读的内容,即是否有对service的操作需求,如果有,则调用svcmgr_handler回调来处理请求的操作。 5. SM维护了一个svclist列表来存储service的信息。 当service在向SM注册时,该service就是一个client,而SM则作为了server。而某个进程需要与service通信时,此时这个进程为client,service才作为server。 应用和service之间的通信会涉及到2次binder通信: 1. 应用向SM查询service是否存在,如果存在获得该service的代理binder,为第一次binder通信; 2. 应用通过binder调用service的方法,为第二次binder通信。 ProcessState ProcessState是以单例模式设计的。每个进程在使用binder机制通信时,均需要维护一个ProcessState实例来描述当前进程在binder通信时的binder状态。 ProcessState有2个主要功能: 1. 创建一个thread,该线程负责与内核中的binder模块进行通信,该线程称为Poolthread; 2. 为指定的handle创建一个BpBinder对象,并管理该进程中所有的BpBinder对象。 在binder IPC中,所有进程均会启动一个thread来负责与BD来直接通信,也就是不听的读写BD。Poolthread的启动方式为, ProcessState::self()->startThreadPool(); BpBinder主要功能是负责client向BD发送调用请求的数据,它是client端binder通信的核心对象,通过调用transact函数向BD发送调用请求的数据。BpBinder构造函数为, BpBinder(int32_t handle); 通过该构造函数可见,BpBinder会将当前通信中server的handle记录下来,当有数据发送时,会通知BD数据的发送目标。 ProcessState通过下述方式来获取BpBinder对象, ProcessState::self()->getContextObject(handle); ProcessState创建的BpBinder实例,一盘情况下回作为参数创建一个client端的service代理接口,形如BpXXXX,例如与SM通信时,client会创建一个代理接口BpServiceManager。 IPCThreadState IPCThreadState是以单例模式设计的。因每个进程只维护了一个ProcessState实例,同时ProcessState只启动一个Poolthread,因此每个进程只需要一个IPCThreadState即可。 Poolthread实际内容为: IPCThreadState::self()->joinThreadPool(); ProcessState中有两个Parcel成员,mIn和mOut。Poolthread会不停查询BD中是否有数据可读,如果有,将其读出并保存到mIn;同时不停检查mOut是否有数据需要向BD发送,如果有,则将其内容写入到BD中。总而言之,从BD中读出的数据保存到mIn,待写入到BD中的数据保存在mOut中。 ProcessState中生成的BpBinder实例通过调用IPCThreadState的transact函数来向mOut中写入数据,这样binder IPC过程的client端的调用请求的发送过程就明了了。 IPCThreadState 有两个重要的函数, talkWithDriver 函数负责从 BD 读写数据, executeCommand 函数负责解析并执行mIn 中的数据。 Binder IPC基本元素分析 基类IInterface 为client/server端提供接口,它的子类分别声明了client/service能够实现的所有的方法。 基类IBinder 定义了binder IPC的通信协议。BBinder和BpBinder均为IBinder的子类,是在IBinder协议框架内进行的收和发操作,构建了基本的binder IPC机制。 基类BpRefBase client端在查询ServerManager获得所需的BpBinder后,BpRefBase负责管理当前获得的BpBinder实例。 接口类BpInterface 如果client端想要使用binder IPC与Service通信,那么首先会从ServiceManager处查询并获得server端service的BpBinder,在client端,这个对象被认为是server端的远程代理。为了使client能够像本地调用一样调用一个远程server,server端需要向client提供一个接口,client在这个接口的基础上创建一个BpInterface,使用这个对象,client的应用能够像本地调用一样直接调用server端的方法。而不用去关心具体的binder IPC实现。 BpInterface的原型: template<typename INTERFACE> class BpInterface : public INTERFACE, public BpRefBase BpInterface是一个模板类,当server提供了INTERFACE接口(形如IXXXService)后,通常会继承BpInterface模板类实现一个BpXXXService: class BpXXXService: public BpInterface<IXXXService> 实际上BpXXXService实现了双继承IXXXService和BpRefBase,这样既实现了service中各方法的本地操作,将每个方法的参数以Parcel的形式发给binder driver;同时又将BpBinder作为了自己的成员来管理,将BpBinder存储在mRemote中,通过调用BpRefBase的remote()来获得BpBinder指针。 接口类BnInterface BnInterface也是一个模板类。在定义native端的service时,基于server提供的INTERFACE接口(IXXXService),通常会继承BnInterface模板类实现一个BnXXXService,而native端的service继承自BnXXXService。BnXXXService定义了一个onTransact函数,这个函数负责解包收到的Parcel并执行client端的请求的方法。 BnInterface的原型是: template<typename INTERFACE> class BnInterface : public INTERFACE, public BBinder BnXXXService形如: class BnXXXService: public BnInterface<IXXXService> IXXXService为client端的代理接口BpXXXService和server端的BnXXXService的共同接口类,这个共同接口类的目的就是保证service方法在C/S两端的一致性。 每个service都可视为一个binder,而真正的service端的binder的操作及状态的维护就是通过继承自BBinder来实现的。BBinder是service作为binder的本质所在。 那么,BBinder与BpBinder的区别是什么呢?BpBinder是client端创建的用于向server发送消息的代理,而BBinder是server端用于接收消息的通道。他们的代码中虽然均有transact方法,但两者的作用不同,BpBinder的transact方法时想IPCThreadState实例发送消息,通知其有消息要发送给binder driver;而BBinder则是当IPCThreadState实例收到binder driver消息时,通过BBinder的transact方法将其传递给它的子类BnXXXService的onTransact函数执行server端的操作。 Parcel类 Parcel是binder IPC中的最基本的通信单元,它存储C/S间函数调用的参数。Parcel只能存储基本的数据类型,如果是复杂的数据类型的话,在存储时,需要将其拆分为基本的数据类型来存储。 binder通信的双方既可以作为client,也可以作为server,此时的binder通信是一个半双工的通信,操作的过程会比单工的情况复杂,但是基本原理是一样的。 Camera Framework的IPC机制 Camera Framework C/S实现类图如下: 仔细阅读本文前面的内容,能够很容易理解Camera Framework采取的C/S结构设计方式。Camera C/S binder IPC通信采用的是半双工通信的方式。client端提供的接口为ICameraClient,分别通过继承BpInterface与BnInterface模板类的方式实现代理BpCameraClient(server端的client代理)与client端本地BnCameraClient,Camera为本地具体的实现;server端提供的接口为ICameraServer,分别通过继承BpInterface与BnInterface模板类的方式实现代理BpCameraService(client端的server代理)与server端本地BnCameraService。 下一篇文章Camera Framework C/S架构服务请求,我们从代码细节入手,用实例阐述Camera中binder IPC通信的具体过程。 转载:http://www.cnblogs.com/yingcare/p/3746751.html
通过该构造函数可见,BpBinder会将当前通信中server的handle记录下来,当有数据发送时,会通知BD数据的发送目标。
ProcessState创建的BpBinder实例,一盘情况下回作为参数创建一个client端的service代理接口,形如BpXXXX,例如与SM通信时,client会创建一个代理接口BpServiceManager。
ProcessState中有两个Parcel成员,mIn和mOut。Poolthread会不停查询BD中是否有数据可读,如果有,将其读出并保存到mIn;同时不停检查mOut是否有数据需要向BD发送,如果有,则将其内容写入到BD中。总而言之,从BD中读出的数据保存到mIn,待写入到BD中的数据保存在mOut中。
BpInterface是一个模板类,当server提供了INTERFACE接口(形如IXXXService)后,通常会继承BpInterface模板类实现一个BpXXXService:
实际上BpXXXService实现了双继承IXXXService和BpRefBase,这样既实现了service中各方法的本地操作,将每个方法的参数以Parcel的形式发给binder driver;同时又将BpBinder作为了自己的成员来管理,将BpBinder存储在mRemote中,通过调用BpRefBase的remote()来获得BpBinder指针。
BnXXXService形如:
IXXXService为client端的代理接口BpXXXService和server端的BnXXXService的共同接口类,这个共同接口类的目的就是保证service方法在C/S两端的一致性。