Binder机制概述

Binder机制概述Binder是Android系统结合自身系统任务特点而实现的一种与传统方式不一样的IPC(Inter-ProcessCommunication)机制。传统的IPC方式有:管道、FIFO、信号、消息队列、信号量、共享内存、Socket。Unix最初只有:管道、FIFO(命名管道)、信号等IPC机制,后来Linux继承和发展了Unix系统的IPC,对其影响比较大的有AT&T的贝尔实验…

Binder是Android系统结合自身系统任务特点而实现的一种与传统方式不一样的IPC(Inter-Process Communication)机制。

传统的IPC方式有:管道、FIFO、信号、消息队列、信号量、共享内存、Socket。

Unix最初只有:管道、FIFO(命名管道)、信号等IPC机制,后来Linux继承和发展了Unix系统的IPC,对其影响比较大的有AT&T的贝尔实验室及BSD。但侧重点有所不同,前者对Unix早期的进程间通信手段进行了系统的改进和扩充,形成了“system V IPC”的消息队列、信号量、共享内存,通信进程局限在单个计算机内;后者则跳过了该限制,形成了基于套接口(socket)的进程间通信机制。

Android是基于Linux的操作系统,而由于Android系统自身任务特点(基于组件方式、扁平化处理、多服务模式),弱化了进程间通信过程,而强调组件方式(四大组件:activity、service、content provider、broadcast receiver)使得传统方式在效率、模式等方面都不大适合,最终有了全新的IPC过程——Binder。

基于Binder的IPC实现过程:
1. 在内核空间创建一个虚拟设备,并生成一个虚拟设备文件“/dev/binder”
2. 利用mmap()接口,把上述创建的内核设备文件的一段空间映射到用户空间
3. 当两个进程进行通信时,只需要一次内存拷贝
4. 系统为每个应用分配UID,可靠的身份标记只有由IPC机制本身在内核中添加(传统IPC只能由用户在数据包里填入UID/PID,这样不可靠,容易被恶意程序利用)。
5. 其次传统IPC访问接入点是开放的,无法建立私有通道。

Android的IPC过程主要是C-S模式的,通信过程需要涉及到应用空间与内核空间。
在应用空间,其通信过程需要涉及到三方:Client(Binder代理端)、Server(Binder响应端)、ServiceManager(管理所有Binder响应端,即所有Service)。
在内核空间,主要与Binder虚拟设备驱动有关(/dev/binder)。

Binder通信的核心是在于其内核空间部分的实现上。

Binder在通信过程中主要实现两个功能:数据传输、RPC(Remote Procedure Call)。

Binder的数据传输通信过程可以简化成如下图所示:
这里写图片描述

但是前面说过,Binder的通信主要完成两个过程:数据传输、RPC过程,上图只是给出了Binder的数据传输过程模型,然而其RPC过程是基于数据传输过程来实现的,其基本框图最终可以简化成如下图所示:
这里写图片描述
在Binder通信过程中,客户端如果需要使用服务端的服务之前,都需要获取对应服务端的Binder代理,对于与ServiceManager(也是一个Binder服务端)通信过程也不例外。只不过,ServiceManager可以看成是一个特殊的Service,其服务代理端获取过程也是比较特殊的(因为ServiceManager的Binder代理的引用句柄等于0,其他所有客户端使用其功能都可以通过句柄0来获取其代理)。除此之外,其他所有服务端的Binder代理都是需要通过访问ServiceManager来直接或者间接获取的(间接获取就是先通过servicemanager获取一个服务的binder代理,然后再访问这个服务来获得另外一个目的服务的代理)。

在讲述Binder的通信过程之前,有必要先呈现一下其涉及到对象的数据结构及继承过程。
这里写图片描述

Binder代理端的Proxy接口及继承过程:

class RefBase {}
class IInterface : public virtual RefBase
class BpRefBase : public virtual RefBase
class IMediaPlayerService: public IInterface
class BpInterface : public IMediaPlayerService, public BpRefBase
class BpMediaPlayerService: public BpInterface<IMediaPlayerService>
//BpMediaPlayerService构造函数,handle为Binder引用代理句柄
explicit BpMediaPlayerService(const sp<IBinder>& impl = BpBinder(handle)) 
: BpInterface<IMediaPlayerService>(impl){}

Binder响应的本地端Native接口及继承过程:

class IBinder : public virtual RefBase
class IInterface : public virtual RefBase
class BBinder : public IBinder
class IMediaPlayerService: public IInterface
class BnInterface : public IMediaPlayerService, public BBinder  //IMediaPlayerService是模版传入
class BnMediaPlayerService: public BnInterface<IMediaPlayerService>  
class MediaPlayerService : public BnMediaPlayerService

其结构中涉及到两个比较重要的宏定义,主要用于实现RPC过程,因为不管是代理端还是响应端,其数据结构的继承关系中都会去继承IMediaPlayerService,展开如下:
DECLARE_META_INTERFACE
路径:IMediaPlayerService.h (../../media/libmedia/include/media/IMediaPlayerService.h)
DECLARE_META_INTERFACE(MediaPlayerService) 宏展开过程如下:

static const ::android::String16 descriptor;
static ::android::sp<IMediaPlayerService> asInterface(const ::android::sp<::android::IBinder>& obj); 
virtual const ::android::String16& getInterfaceDescriptor() const;
IMediaPlayerService();    
virtual ~IMediaPlayerService(); 

IMPLEMENT_META_INTERFACE
路径:IMediaPlayerService.cpp (../../media/libmedia/include/media/IMediaPlayerService.cpp)
IMPLEMENT_META_INTERFACE(MediaPlayerService, “android.media.IMediaPlayerService”) 宏展开过程如下:

const ::android::String16 IMediaPlayerService::descriptor("android.media.IMediaPlayerService");           
const ::android::String16& IMediaPlayerService::getInterfaceDescriptor() const
{
return IMediaPlayerService::descriptor;
}              

IBinder::queryLocalInterface() //Binder.cpp (native\libs\binder) 
class BpMediaPlayerService: public BpInterface<IMediaPlayerService>  //IMediaPlayerService.cpp (av\media\libmedia)
explicit BpMediaPlayerService(const sp<IBinder>& impl) //BpMediaPlayerService构造函数
: BpInterface<IMediaPlayerService>(impl)
{}

::android::sp<IMediaPlayerService> IMediaPlayerService::asInterface(const ::android::sp<::android::IBinder>& obj)
{
    ::android::sp<IMediaPlayerService> intr; 
    if (obj != NULL) {                                      
        intr = static_cast<IMediaPlayerService*>(obj->queryLocalInterface(IMediaPlayerService::descriptor).get());  
    //IBinder::queryLocalInterface()查询都是返回空的
        if (intr == NULL) {
            intr = new BpMediaPlayerService(obj);
        }                                                        
    }                                                            
    return intr;
}                                                                
IMediaPlayerService::IMediaPlayerService() {}
IMediaPlayerService::~IMediaPlayerService() {}

宏中最重要的一个函数就是IMediaPlayerService::asInterface,告知如何生成一个客户端的Binder代理过程,在此不会详细展开讲解,因为只是概述,后续章节会详细介绍。

以上只是Android Binder机制的简单概述,主要做为后续章节的引言,在接下去的章节中,会详细介绍数据的交互过程以及RPC过程。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/36314.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注