博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android C++底层Binder通信机制原理分析总结【通俗易懂】
阅读量:657 次
发布时间:2019-03-15

本文共 4595 字,大约阅读时间需要 15 分钟。

Android C++底层Binder通信机制原理总结:

通过transact()方法可以向远端的IBinder对象发出调用,再通过onTransact()函数让你自己的远程对象能够响应接收到的调用。

例如MediaRecorder的继承关系(向右箭头表示继承关系,#XXX#中间是关键方法,/斜线表示多继承):

客户端:

1、MediaRecorder->BnMediaRecorderClient#onTransact()#->BnInterface->
BBinder#transact()#(->IBinder->RefBase)/IMediaRecorderClient#notify(xx)/asInterface(IBinder obj)#(->IInterface->RefBase)
2、代理:BpMediaRecorderClient(IBinder impl)->BpInterface(IBinder remote)->
BpRefBase(IBinder o)#remote()#->RefBase/IMediaRecorderClient#notify(xx)/asInterface(IBinder obj)#(->IInterface->RefBase)

服务器:

3、MediaRecorderClient->BnMediaRecorder->BnInterface->BBinder(->IBinder->RefBase)/IMediaRecorder(->IInterface->RefBase)
4、BpMediaRecorder(IBinder impl)->BpInterface(IBinder remote)->
BpRefBase(IBinder o)#remote()#->RefBase/IMediaRecorderClient#notify(xx)/asInterface(IBinder obj)#(->IInterface->RefBase)

5、【interface_cast模板方法】即asInterface(IBinder obj)是一个宏定义生成的函数,通过缓存查找或直接new一个Bp对象(BpMediaRecorderClient(BpBinder->IBinder obj)),

返回父类型对象即IBpMediaRecorderClient(IBinder obj)对象,因此也就创建了一个Bp代理对象;

6、以上可总结为:

6.1、BnXXX或BpXXX都派生自两个类:
class BpXXX : public IXXX, public BpRefBase;
class BnXXX : public IXXX, public BBinder;
6.2、BpXXX和BnXXX都派生自IXXX,IXXX可理解为定义业务逻辑,但BnXXX和BpXXX中具体实现方式却不同,如下分析:
BpXXX中:作为代理端,把对应的binder_transaction_data打包之后,通过BpRefBase中的mRemote即BpBinder对象实例发送出去,并等待结果。
BnXXX中:作为实现端,实现与BpXXX中对应的真正的业务逻辑,通过调用BnXXX派生类中的方法来实现,如MediaRecorderClient实现类;
6.3、IBinder用于进行进程间通信:
BpRefBase中的remote()方法返回的mRemote即BpBinder对象实例用来和Binder驱动交互使用(通过BpBinder.transact(xxx)调用IPCThreadState.transact(xxx)方法,
最后调用IPCThreadState.talkWithDriver(bool)方法中使用ioctl()函数将Parcel类型的mOut中缓存数据写入Binder驱动共享内存区域,并获取mIn返回值Parcel数据);
BBinder(transact()到onTransact()的调用)是从Binder驱动中接收相关请求,并进行相关处理的;
BpBinder(remote())则是和BinderDriver进行互通的;

7、Binder机制中与Binder驱动交互的桥梁:两个非常重要的类:ProcessState和IPCThreadState类。

ProcessState:是Client和Server两端公共的部分,作为Binder通信的基础。并且是个singleton单例类,每个进程只有一个对象,
该对象负责打开Binder驱动,建立线程池,使得该进程中的所有线程都能通过Binder通信。
IPCThreadState:是每个线程中都有一个IPCThreadState对象实例记录在Linux线程的上下文附属数据中,主要负责Binder的读取、写入和请求处理,
并且它在创建时会记录一个ProcessState类型的mProcess成员变量,以便用于获取到Binder句柄,从而进行binder_transaction_data事务数据在两个进程间的通信。

IPC通信简单分析例如:

1、 注册相关服务:【frameworks/av/media/mediaserver/main_mediaserver.cpp】中

int main(int argc __unused, char **argv __unused){
sp
proc(ProcessState::self());// 初始化注册服务管理中心即BpServiceManager sp
sm(defaultServiceManager()); // 实例化相关服务 MediaPlayerService::instantiate(); ResourceManagerService::instantiate(); registerExtensions();// 进入线程循环 ProcessState::self()->startThreadPool(); IPCThreadState::self()->joinThreadPool();}

分析:系统启动时init进程会初始化所有多媒体相关的服务在服务管理中心,以便此后直接进行获取。

void MediaPlayerService::instantiate() {
defaultServiceManager()->addService( String16("media.player"), new MediaPlayerService());}

分析:向注册服务管理中心注册自己的服务实现者即Bn实现对象,该服务对应名称是"media.player",以提供给Bp代理者代理操作实现的业务功能。

2、向注册服务管理中心获取自己的服务即Bp实现对象,也是Bn对象的在客户端的代理操作对象。

MediaRecorder::MediaRecorder(const String16& opPackageName) : mSurfaceMediaSource(NULL){
const sp
service(getMediaPlayerService()); if (service != NULL) {
mMediaRecorder = service->createMediaRecorder(opPackageName); }}//【IMediaDeathNotifier.cpp】MediaRecorder继承了IMediaDeathNotifier类IMediaDeathNotifier::getMediaPlayerService(){
Mutex::Autolock _l(sServiceLock);if (sMediaPlayerService == 0) {
// 初始化注册服务管理中心即BpServiceManager sp
sm = defaultServiceManager(); sp
binder; // 通过响应服务注册时的服务名称【"media.player"】获取注册过的服务 binder = sm->getService(String16("media.player")); // 最后使用interface_cast转换成对应服务取得Bp代理对象 sMediaPlayerService = interface_cast
(binder); } return sMediaPlayerService;}

分析:MediaRecorder通过getMediaPlayerService()从ServiceManager层获取到此前已经注册进Service的BpMediaPlayerService服务,通过该服务在跨进程通信时通过createMediaRecorder()函数发送CREATE_MEDIA_RECORDER消息通知MediaPlayerService(BnMediaPlayerService)的BnMediaPlayerService::onTransact()方法,构造了一个MediaRecorderClient对象,并将该client对象放入MediaPlayerService类的全局SortedVector类型的列表中,然后返回结果client。

并且在构造MediaRecoderClient时通过AVMediaServiceFactory创建了一个StageFrightRecorder对象,该对象才是真正录制相关功能实现者如数据处理、编码、录制行为控制(如prepare、start、pause、resume、stop等)等。

例如:

setupMediaSource: 通过setupCameraSource去绑定CameraSource的listener,从而获取到driver层返回的数据。
setupVideoEncoder: 根据上层传入的video编码格式来创建对应的MediaCodecSource即Video编码器。
setupAudioEncoder: 根据上层传入的audio编码格式来创建对应的MediaCodecSource即Audio编码器。
使用MediaWriter(MPEG4Writer): 在MPEG4Writer的startWriterThread中开启MediaWriter线程,分track读取并在Track->dump(fd,args)中write(fd,result.string(),result.size())写入数据到最终文件中。

转载地址:http://sapmz.baihongyu.com/

你可能感兴趣的文章