在Binder系列1 Binder总体设计思想中,主要从宏观上讲了 Binder 的总体设计思想和一些关键部分的设计细节,比如接收缓存管理,接收线程优化和线程池管理,接收包管理等.在系列2中会进一步细化 Binder 的概念和介绍实现 Binder 通信架构所用到的相关接口和类.
一 什么是Binder
简单地说,Binder 是 Android 平台上的一种跨进程通信技术。该技术最早并不是由 Google 公司提出的,它的前身是 Be Inc 公司开发的 OpenBinder,而且在 Palm 中也有应用。后来 OpenBinder 的作者 Dianne Hackborn 加入了 Google公司,并负责Android平台的开发工作,所以把这项技术也带进了 Android.
在 Android 的应用层次上,基本上已经没有过去的进程概念了。取而代之的都是 Activity,Service,BroadcastReceiver,和 ContentProvider 等各个组件.然而在实现层次,它毕竟还是要建构在一个个进程之上的。实际上,在 Android 内部,那些支撑应用程序的各个组件,往往会身处于不同的进程,那么应用程序的底层,必然会牵涉到大量的跨进程通信。为了保证通信的高效性,Android 提供了 Binder 机制.
Binder 机制具有两层含义:
1) 是一种跨进程通信手段(IPC,Inter-Process Communication)。
2) 是一种远程过程调用手段(RPC,Remote Procedure Call)。
从实现的角度来说,Binder 的核心被实现成了一个 Linux 驱动程序,并运行于内核态。这样它才能具有强大的跨进程访问能力。
1.1 简述Binder的跨进程通信机制
为了理解 Binder,我们可以先画一张最简单的跨进程通信示意图:
这个很容易理解,不需赘言。到了 Android 平台上,IPC 机制就变成了 Binder 机制,情况类似,只不过为了便于说明问题,我们需要稍微调整一下示意图:
图中A侧的圆形块,表示“Binder代理方”也叫 Binder 引用,主要用于向远方发送语义,而B侧的方形块
则表示“Binder响应方”也叫 Binder 实体,主要用于响应语义。需要说明的是,这种图形表示方法只是为了便于理解,个人觉得这种图形非常简便,所以在分析 Android 架构时,会经常使用这种表示法。
在后文中,我们可以看到,Binder 代理方对应于 C++ 层次的 BpBinder 对象,而 Binder 响应方则对应于 BBinder 对象。这两个对象在后文会详细阐述,此处不必太细究。
然而,上图的 Binder 代理方主要只负责了“传递信息”的数据传输工作,并没有起到“远程过程调用”的作用,如果要支持远程过程调用,我们还必须提供“接口代理方”和“接口实现体”。这样,我们的示意图就需要再调整一下,如下:
从图中可以看到,A进程并不直接和 BpBinder(Binder代理)打交道,而是通过调用 BpInterface(接口代理)的成员函数来完成远程调用的。此时,BpBinder 已经被聚合进 BpInterface 了,它在 BpInterface 内部完成了一切跨进程通信的机制。另一方面,与 BpInterface 相对的响应端实体就是 BnInterface(接口实现)了。需要注意的是,BnInterface 是继承于 BBinder 的,它并没有采用聚合的方式来包含一个 BBinder 对象,所以上图中B侧的 BnInterface 块和 BBinder 块的背景图案是相同的,BpBinder 是聚合进 BpInterface,而 BnInterface 是继承自 BBinder,了解和理解这一点非常重要。
这样看来,对于远程调用的客户端而言,主要搞的就是两个东西,一个是 Binder 代理:BpBinder,另外一个就是“接口代理”:BpInterface。而服务端主要搞的则是“接口实现体”:BnInterface。因为 Binder 是一种跨进程通信机制,为了便于管理Binder服务,和便于 Client 获取 Binder 引用,Binder 机制就搞了一个专门的管理器来为通信两端牵线搭桥,这个管理器就是 SMgr。不过目前我们可以先放下 ServiceManager,在Binder系列3 ServiceManager启动和实现中会详细研究。
二 Binder相关接口和类
由于 Android 系统是分层次的系统,所以跨进程通信的 Binder,不但会在底层使用,也会在上层使用,所以需要提供 Java 和C++ 两个层次的支持。
2.1 Java层次的Binder元素
Java 层次里并没有我们前文图中所表示的 BpBinder、BpInterface、BBinder、BnInterface 等较低层次的概念,取而代之的是IBinder 接口、IInterface 等接口。Android 要求所有的 Binder 实体都必须实现 IBinder 接口,该接口的定义截选如下:
frameworks/base/core/java/android/os/IBinder.java
public interface IBinder
{
. . . . . .
public String getInterfaceDescriptor() throws RemoteException;
public boolean pingBinder();
public boolean isBinderAlive();
public IInterface queryLocalInterface(String descriptor);
public void dump(FileDescriptor fd, String[] args) throws RemoteException;
public void dumpAsync(FileDescriptor fd, String[] args) throws RemoteException;
public void shellCommand(@Nullable FileDescriptor in, @Nullable FileDescriptor out,
@Nullable FileDescriptor err,
@NonNull String[] args, @Nullable ShellCallback shellCallback,
@NonNull ResultReceiver resultReceiver) throws RemoteException;
public boolean transact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags)
throws RemoteException;
public interface DeathRecipient {
public void binderDied();
}
public void linkToDeath(DeathRecipient recipient, int flags)throws RemoteException;
public boolean unlinkToDeath(DeathRecipient recipient, int flags);
}
另外,不管是代理方还是实体方,都必须实现 IInterface 接口:
public interface IInterface
{
/**
* Retrieve the Binder object associated with this interface.
* You must use this instead of a plain cast, so that proxy objects
* can return the correct result.
*/
public IBinder asBinder();
}
Java 层次中,与 Binder 相关的接口或类的继承关系如下:
在实际使用中,我们并不需要编写上图的 XXXXNative、XXXXProxy,它们会由 ADT 根据我们编写的 AIDL 脚本自动生成。用户只需继承 XXXXNative 编写一个具体的 XXXXService 即可,这个 XXXXService 就是远程通信的服务实体类,而 XXXXProxy 则是其对应的代理类。
关于 Java 层次的 Binder 组件,我们就先说这么多,主要是先介绍一个大概。就研究跨进程通信而言,其实质内容基本上都是在 C++ 层次,Java 层次只是一个壳而已。以后我会写专文来打通 Java 层次和 C++ 层次,看看它们是如何通过 JNI 技术关联起来的。现在我们还是把注意力集中在 C++ 层次吧。
2.2 C++层次的Binder元素
在 C++ 层次,就能看到我们前文所说的 BpBinder 类和 BBinder 类了。这两个类都继承于 IBinder,IBinder 的定义截选如下:
frameworks/native/include/binder/IBinder.h
class IBinder : public virtual RefBase
{
public:
.........
IBinder();
virtual sp<IInterface> queryLocalInterface(const String16& descriptor);
virtual const String16& getInterfaceDescriptor() const = 0;
virtual bool isBinderAlive() const = 0;
virtual status_t pingBinder() = 0;
virtual status_t dump(int fd, const Vector<String16>& args) = 0;
static status_t shellCommand(const sp<IBinder>& target, int in, int out, int err,
Vector<String16>& args, const sp<IShellCallback>& callback,
const sp<IResultReceiver>& resultReceiver);
virtual status_t transact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0) = 0;
class DeathRecipient : public virtual RefBase {
public:
virtual void binderDied(const wp<IBinder>& who) = 0;
};
virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
void* cookie = NULL,
uint32_t flags = 0) = 0;
virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient,
void* cookie = NULL,
uint32_t flags = 0,
wp<DeathRecipient>* outRecipient = NULL) = 0;
virtual bool checkSubclass(const void* subclassID) const;
typedef void (*object_cleanup_func)(const void* id, void* obj, void* cleanupCookie);
virtual void attachObject( const void* objectID,
void* object,
void* cleanupCookie,
object_cleanup_func func) = 0;
virtual void* findObject(const void* objectID) const = 0;
virtual void detachObject(const void* objectID) = 0;
virtual BBinder* localBinder();
virtual BpBinder* remoteBinder();
protected:
virtual ~IBinder();
private:
};
需要重点关注 transact 函数,这个函数在继承于 IBinder 的 BpBinder 和 BBinder 中都有使用,用来传输数据;还要关注localBinder 函数和 remoteBinder 函数,这2个函数的返回值分别为 BBinder 和 BbBinder,分别表示 Server 端的 Binder 实体和Client 端的 Binder 代理.
C++ 层次的继承关系图如下:
以上各个接口和类的继承关系一定要深刻理解并牢记,这些继承关系是 Binder 跨进程通信的具体实现方式.其中有以下几个很关键的类:
- BpBinder
- BpInterface
- BBinder
- BnInterface
它们扮演着很重要的角色。
2.2.1 BpBinder
BpBinder的定义截选如下:
class BpBinder : public IBinder
{
public:
BpBinder(int32_t handle);
inline int32_t handle() const { return mHandle; }
virtual const String16& getInterfaceDescriptor() const;
virtual bool isBinderAlive() const;
virtual status_t pingBinder();
virtual status_t dump(int fd, const Vector<String16>& args);
virtual status_t transact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
void* cookie = NULL,
uint32_t flags = 0);
virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient,
void* cookie = NULL,
uint32_t flags = 0,
wp<DeathRecipient>* outRecipient = NULL);
virtual void attachObject( const void* objectID,
void* object,
void* cleanupCookie,
object_cleanup_func func);
virtual void* findObject(const void* objectID) const;
virtual void detachObject(const void* objectID);
virtual BpBinder* remoteBinder();
status_t setConstantData(const void* data, size_t size);
void sendObituary();
.............
protected:
virtual ~BpBinder();
virtual void onFirstRef();
virtual void onLastStrongRef(const void* id);
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
private:
const int32_t mHandle;
............
};
作为代理端的核心,BpBinder 最重要的职责,就是实现跨进程传输的传输机制,至于具体传输的是什么语义,它并不关心。我们观察它的 transact() 函数的参数,可以看到所有的语义都被打包成 Parcel 了。还需要关注 mHandle 这个成员变量,这个就是代理端 Binder 引用的句柄.其他的成员函数,我们先不深究,待我们储备了足够的基础知识后,再回过头研究它们不迟。
2.2.2 BpInterface
另一个重要的类是BpInterface,它的定义如下:
template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase
{
public:
explicit BpInterface(const sp<IBinder>& remote);
protected:
virtual IBinder* onAsBinder();
};
其基类 BpRefBase 的定义如下:
class BpRefBase : public virtual RefBase
{
protected:
explicit BpRefBase(const sp<IBinder>& o);
virtual ~BpRefBase();
virtual void onFirstRef();
virtual void onLastStrongRef(const void* id);
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
inline IBinder* remote() { return mRemote; }
inline IBinder* remote() const { return mRemote; }
private:
BpRefBase(const BpRefBase& o);
BpRefBase& operator=(const BpRefBase& o);
IBinder* const mRemote;
RefBase::weakref_type* mRefs;
std::atomic<int32_t> mState;
};
BpInterface 使用了模板技术,并且它继承了 BpRefBase,而 BpRefBase 中存在一个 IBinder 类型的变量 mRemote,所以BpInterface 先天上就聚合了一个 mRemote 成员,这个成员记录的就是前面所说的 BpBinder 对象。这个就是为什么我们前面说的 BpBinder 是聚合在 BpInterface 中的原因.以后我们还需要继承 BpInterface<Ixxxx> 实现我们自己的代理类。
在实际的代码中,我们完全可以创建多个聚合同一 BpBinder 对象的代理对象,这些代理对象就本质而言,对应着同一个远端Binder 实体。在 Android 框架中,常常把指向同一 Binder 实体的多个代理称为 token,这样即便这些代理分别处于不同的进程中,它们也具有了某种内在联系。这个知识点需要大家关注。
2.2.3 BBinder
Binder 远程通信的 Server 端的 Binder 实体,必须继承于 BBinder 类,该类和 BpBinder 相对,主要关心的只是传输方面的东西,不关心所传输的语义。
class BBinder : public IBinder
{
public:
BBinder();
virtual const String16& getInterfaceDescriptor() const;
virtual bool isBinderAlive() const;
virtual status_t pingBinder();
virtual status_t dump(int fd, const Vector<String16>& args);
virtual status_t transact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
void* cookie = NULL,
uint32_t flags = 0);
virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient,
void* cookie = NULL,
uint32_t flags = 0,
wp<DeathRecipient>* outRecipient = NULL);
virtual void attachObject( const void* objectID,
void* object,
void* cleanupCookie,
object_cleanup_func func);
virtual void* findObject(const void* objectID) const;
virtual void detachObject(const void* objectID);
virtual BBinder* localBinder();
protected:
virtual ~BBinder();
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
private:
BBinder(const BBinder& o);
BBinder& operator=(const BBinder& o);
.........
};
上面有二个函数需要重点关注:transact 函数和 onTransact 函数,我们先看上面的 transact() 成员函数,transact 函数的代码如下:
frameworks/native/libs/binder/Binder.cpp
status_t BBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
data.setDataPosition(0);
status_t err = NO_ERROR;
switch (code) {
case PING_TRANSACTION:
reply->writeInt32(pingBinder());
break;
default:
err = onTransact(code, data, reply, flags);
break;
}
if (reply != NULL) {
reply->setDataPosition(0);
}
return err;
}
看到了吗,transact() 内部会调用 onTransact(),这样当 Server 端的 Binder 实体继承了 BBinder,并且实现其中的 onTransact 函数后,就会自动调用到这个 Binder 实体实现的 onTransact() 里。这个 onTransact() 的一大作用就是接收跨进程传输过来的数据包,并解析数据包中的语义。
2.2.4 BnInterface
远程通信目标端的另一个重要类是 BnInterface<>,它是与 BpInterface<> 相对应的模板类,比较关心传输的语义。一般情况下,服务端并不直接使用 BnInterface<>,而是使用它的某个子类。为此,我们需要编写一个新的 BnXXX子类,继承 BnInterface<>,因为 BnInterface<> 又继承于 BBinder,所以这个 BnXXX 子类继承了 onTransact 函数,并重载实现了 onTransact() 成员函数,用来具体的解析通过 Binder 机制传输过来的数据包。
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();
};
如上所示,BnInterface<> 继承于 BBinder,但它并没有实现一个默认的 onTransact() 成员函数,所以在远程通信时,前文所说的BBinder::transact() 调用的 onTransact() 就是调用的 BnInterface<> 的某个子类 BnXXX 的 onTransact() 成员函数。
2.3 几个重要的C++宏或模板
为了便于编写新的接口和类,Android 在 C++ 层次提供了几个重要的宏和模板,比如我们在 IInterface.h 文件中,可以看到DECLARE_META_INTERFACE、IMPLEMENT_META_INTERFACE 的定义。
2.3.1 DECLARE_META_INTERFACE()
#define DECLARE_META_INTERFACE(INTERFACE) \
static const ::android::String16 descriptor; \
static ::android::sp<I##INTERFACE> asInterface( \
const ::android::sp<::android::IBinder>& obj); \
virtual const ::android::String16& getInterfaceDescriptor() const; \
I##INTERFACE(); \
virtual ~I##INTERFACE();
我们举个实际的例子,来说明如何使用这个宏:
framework/av/media/libmedia/include/media/IMediaPlayerService.h
class IMediaPlayerService: public IInterface
{
public:
DECLARE_META_INTERFACE(MediaPlayerService);
.............
virtual void addBatteryData(uint32_t params) = 0;
virtual status_t pullBatteryData(Parcel* reply) = 0;
};
上例中 IMediaPlayerService 内部使用了 DECLARE_META_INTERFACE(MediaPlayerService),我们把宏展开后,可以看到IMediaPlayerService 类的定义相当于:
class IMediaPlayerService: public IInterface
{
public:
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();
.............
virtual void addBatteryData(uint32_t params) = 0;
virtual status_t pullBatteryData(Parcel* reply) = 0;
};
宏展开的部分就是中间那6行代码,其中最关键的就是 asInterface() 函数了,这个函数将承担把继承于 IBinder 的 BpBinder 打包成 BpInterface 的职责。
2.3.2 IMPLEMENT_META_INTERFACE()
与 DECLARE_META_INTERFACE 相对的就是 IMPLEMENT_META_INTERFACE 宏。它的定义如下:
#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> I##INTERFACE::asInterface( \
const ::android::sp<::android::IBinder>& obj) \
{ \
::android::sp<I##INTERFACE> intr; \
if (obj != NULL) { \
intr = static_cast<I##INTERFACE*>( \
obj->queryLocalInterface( \
I##INTERFACE::descriptor).get()); \
if (intr == NULL) { \
intr = new Bp##INTERFACE(obj); \
} \
} \
return intr; \
} \
I##INTERFACE::I##INTERFACE() { } \
I##INTERFACE::~I##INTERFACE() { }
其中,实现了关键的 asInterface() 函数。
实际使用 IMPLEMENT_META_INTERFACE 时,我们只需把它简单地写在 Binder 实体所处的 cpp 文件中即可,举例如下:
framework/av/media/libmedia/IMediaPlayerService.cpp
IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.media.IMediaPlayerService");
// ----------------------------------------------------------------------
status_t BnMediaPlayerService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch (code) {
case CREATE: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
sp<IMediaPlayerClient> client =
interface_cast<IMediaPlayerClient>(data.readStrongBinder());
audio_session_t audioSessionId = (audio_session_t) data.readInt32();
sp<IMediaPlayer> player = create(client, audioSessionId);
reply->writeStrongBinder(IInterface::asBinder(player));
return NO_ERROR;
} break;
case CREATE_MEDIA_RECORDER: {
CHECK_INTERFACE(IMediaPlayerService, data, reply);
const String16 opPackageName = data.readString16();
sp<IMediaRecorder> recorder = createMediaRecorder(opPackageName);
reply->writeStrongBinder(IInterface::asBinder(recorder));
return NO_ERROR;
} break;
............................
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
其中的 IMPLEMENT_META_INTERFACE(MediaPlayerService, "android.media.IMediaPlayerService");根据模板展开为:
const ::android::String16 IMediaPlayerService::descriptor("android.media.IMediaPlayerService");
const ::android::String16&
IMediaPlayerService::getInterfaceDescriptor() const{
return IMediaPlayerService::descriptor;
}
::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());
if (intr == NULL) {
intr = new BpMediaPlayerService(obj);
}
}
return intr;
}
IMediaPlayerService::IMediaPlayerService() { }
IMediaPlayerService::~IMediaPlayerService() { }
其中重点实现了 asInterface() 成员函数。请注意,asInterface() 函数中会先尝试调用 IBinder 的 queryLocalInterface() 函数来获取 intr。此时,如果 asInterface() 的 obj 参数是个代理对象(BpBinder),那么 intr = static_cast<MediaPlayerService*>(obj->queryLocalInterface(...) 一句得到的 intr 基本上就是 NULL 了。这是因为除非用户编写的代理类重载 queryLocalInterface() 函数,否则只会以默认函数为准。而 IBinder 类中的默认 queryLocalInterface() 函数如下:
frameworks/native/libs/binder/Binder.cpp
sp<IInterface> IBinder::queryLocalInterface(const String16& /*descriptor*/)
{
return NULL;
}
另一方面,如果 obj 参数是个实现体对象(BnInterface对象)的话,那么 queryLocalInterface() 函数的默认返回值就是实体对象的 this 指针了,代码如下:
frameworks/native/include/binder/IInterface.h
template<typename INTERFACE>
inline sp<IInterface> BnInterface<INTERFACE>::queryLocalInterface(
const String16& _descriptor)
{
if (_descriptor == INTERFACE::descriptor) return this;
return NULL;
}
在我们所举的 MediaPlayerService 例子中,我们要研究的是如何将 BpBinder 转成 BpInterface,所以现在我们只阐述 obj 参数为BpBinder 的情况。此时 asInterface() 函数中 obj->queryLocalInterface() 的返回值为 NULL,于是 asInterface() 会走到 new BpMediaPlayerService(obj) 一句,这一句最关键。我们知道,BpMediaPlayerService 继承于BpInterface<IMediaPlayerService>,所以此时所创建的 BpMediaPlayerService 对象,正是可被 Client 端使用的 BpInterface 代理对象。
BpMediaPlayerService 的定义如下:
class BpMediaPlayerService: public BpInterface<IMediaPlayerService>
{
public:
explicit BpMediaPlayerService(const sp<IBinder>& impl)
: BpInterface<IMediaPlayerService>(impl)
{
}
virtual sp<IMediaMetadataRetriever> createMetadataRetriever()
{
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
remote()->transact(CREATE_METADATA_RETRIEVER, data, &reply);
return interface_cast<IMediaMetadataRetriever>(reply.readStrongBinder());
}
virtual sp<IMediaPlayer> create(
const sp<IMediaPlayerClient>& client, audio_session_t audioSessionId) {
Parcel data, reply;
data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor());
data.writeStrongBinder(IInterface::asBinder(client));
data.writeInt32(audioSessionId);
remote()->transact(CREATE, data, &reply);
return interface_cast<IMediaPlayer>(reply.readStrongBinder());
}
.....................
};
同学们有没有发现,在 BpMediaPlayerService 中,每个函数最后都会调用 remote()->transact() 函数,其中的 remote() 函数就是在 BpRefBase 中定义的,返回的是其中的变量 mRemote,这个变量前面在讨论 BpRefBase 中已经说明了,它就是 BpBinder,由此可以看到代理端的 BpXXX 中所调用的函数,最后都会通过调用聚合在其中的 BpBinder 的 transact() 函数来完成跨进程传输,这个一定要记住和理解.
至此,IMPLEMENT_META_INTERFACE 宏和 asInterface() 函数的关系就分析完毕了。
2.3.3 interface_cast
不过,我们经常使用的其实并不是 asInterface() 函数,而是 interface_cast(),它简单包装了 asInterface():
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
以上就是关于 C++ 层次中一些 Binder 元素的介绍,下面我们再进一步分析其他细节。
三 ProcessState
前文我们已经提到过,在 Android 的上层架构中,已经大幅度地弱化了进程的概念。应用程序员能看到的主要是 activity、service、content provider 等概念,再也找不到以前熟悉的 main() 函数了。然而,底层程序(C++层次)毕竟还是得跑在一个个进程之上,现在我们就来看底层进程是如何运用 Binder 机制来完成跨进程通信的。
在每个进程中,会有一个全局的 ProcessState 对象。这个很容易理解,ProcessState 的字面意思不就是“进程状态”吗,当然应该是每个进程对应一个 ProcessState。ProcessState 的定义位于 frameworks/native/include/binder/ProcessState.h 中,如下:
class ProcessState : public virtual RefBase
{
public:
static sp<ProcessState> self();
static sp<ProcessState> selfOrNull();
/* initWithDriver() can be used to configure libbinder to use
* a different binder driver dev node. It must be called *before*
* any call to ProcessState::self(). /dev/binder remains the default.
*/
static sp<ProcessState> initWithDriver(const char *driver);
void setContextObject(const sp<IBinder>& object);
sp<IBinder> getContextObject(const sp<IBinder>& caller);
void setContextObject(const sp<IBinder>& object,
const String16& name);
sp<IBinder> getContextObject(const String16& name,
const sp<IBinder>& caller);
void startThreadPool();
typedef bool (*context_check_func)(const String16& name,
const sp<IBinder>& caller,
void* userData);
bool isContextManager(void) const;
bool becomeContextManager(
context_check_func checkFunc,
void* userData);
sp<IBinder> getStrongProxyForHandle(int32_t handle);
wp<IBinder> getWeakProxyForHandle(int32_t handle);
void expungeHandle(int32_t handle, IBinder* binder);
void spawnPooledThread(bool isMain);
status_t setThreadPoolMaxThreadCount(size_t maxThreads);
void giveThreadPoolName();
String8 getDriverName();
ssize_t getKernelReferences(size_t count, uintptr_t* buf);
private:
friend class IPCThreadState;
ProcessState(const char* driver);
~ProcessState();
ProcessState(const ProcessState& o);
ProcessState& operator=(const ProcessState& o);
String8 makeBinderThreadName();
struct handle_entry {
IBinder* binder;
RefBase::weakref_type* refs;
};
handle_entry* lookupHandleLocked(int32_t handle);
String8 mDriverName;
int mDriverFD;
void* mVMStart;
// Protects thread count variable below.
pthread_mutex_t mThreadCountLock;
pthread_cond_t mThreadCountDecrement;
// Number of binder threads current executing a command.
size_t mExecutingThreadsCount;
// Maximum number for binder threads allowed for this process.
size_t mMaxThreads;
// Time when thread pool was emptied
int64_t mStarvationStartTimeMs;
mutable Mutex mLock; // protects everything below.
Vector<handle_entry>mHandleToObject;
bool mManagesContexts;
context_check_func mBinderContextCheckFunc;
void* mBinderContextUserData;
KeyedVector<String16, sp<IBinder> >
mContexts;
String8 mRootDir;
bool mThreadPoolStarted;
volatile int32_t mThreadPoolSeq;
};
我们知道,Binder 内核被设计成一个驱动程序,所以 ProcessState 里专门搞了个 mDriverFD 域,来记录 Binder 驱动对应的文件句柄值,以便随时和 Binder 驱动通信。ProcessState 对象采用了典型的单例模式,在一个应用进程中,只会有唯一的一个ProcessState 对象,它将被进程中的多个线程共用,因此每个进程里的线程其实是共用所打开的那个驱动句柄(mDriverFD)的,示意图如下:
每个进程基本上都是这样的结构,组合起来的示意图就是
我们常见的使用 ProcessState 的代码如下:
int main(int argc __unused, char **argv __unused)
{
signal(SIGPIPE, SIG_IGN);
sp<ProcessState> proc(ProcessState::self());
...........
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
因为 ProcessState 采用的是单例模式,所以它的构造函数是 private 的,我们只能通过调用 ProcessState::self() 来获取进程中唯一的一个 ProcessState 对象。self() 函数的代码如下:
frameworks/native/libs/binder/ProcessState.cpp
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
return gProcess;
}
gProcess = new ProcessState("/dev/binder");
return gProcess;
}
ProcessState 对象构造之时,就会打开 Binder 驱动:
ProcessState::ProcessState(const char *driver)
: mDriverName(String8(driver))
, mDriverFD(open_driver(driver))
, mVMStart(MAP_FAILED)
, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
, mExecutingThreadsCount(0)
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
, mStarvationStartTimeMs(0)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
{
if (mDriverFD >= 0) {
// mmap the binder, providing a chunk of virtual address space to receive transactions.
mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
// *sigh*
ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
close(mDriverFD);
mDriverFD = -1;
mDriverName.clear();
}
}
LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating.");
}
注意上面那句 mDriverFD(open_driver(driver)),其中的 open_driver() 就负责打开“/dev/binder”驱动:
static int open_driver(const char *driver)
{
int fd = open(driver, O_RDWR | O_CLOEXEC);
if (fd >= 0) {
int vers = 0;
status_t result = ioctl(fd, BINDER_VERSION, &vers);
if (result == -1) {
ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
close(fd);
fd = -1;
}
if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
ALOGE("Binder driver protocol(%d) does not match user space protocol(%d)! ioctl() return value: %d",
vers, BINDER_CURRENT_PROTOCOL_VERSION, result);
close(fd);
fd = -1;
}
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
if (result == -1) {
ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
}
} else {
ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno));
}
return fd;
}
从以上代码可以看到,open_driver 函数打开了“/dev/binder”驱动,获得了文件描述符fd,然后返回这个fd,并赋值给了mDriverFD
ProcessState 中还有一个域很重要,是 mHandleToObject:Vector<handle_entry>mHandleToObject,这个里边存储的是BpBinder,这个 mHandleToObject 向量表,记录了本进程中所有的 BpBinder,这个非常重要.我们前文已经说过,BpBinder 是代理端的核心,现在终于看到它的藏身之处了。在 Binder 架构中,Client 进程是通过“Binder句柄”来找到对应的 BpBinder 的。从这张向量表中我们可以看到,那个句柄值其实对应着这个向量表的下标。这张表的子项类型为 handle_entry,定义如下:
struct handle_entry {
IBinder* binder;
RefBase::weakref_type* refs;
};
其中的 binder 域,记录的就是 BpBinder 对象。
四 总结
本篇文章主要介绍了 Binder 的概念和 Binder 架构的具体实现方式,包括涉及到的相关接口和类,比如 BpBinder,BpInterface,BBinder,BnInterface 以及之间的相互继承关系,还介绍了便于生成 BpInterface<IXXX> 而设计的相关模板类,并举了具体的例子来便于理解,最后介绍了进程相关的 ProcessState.大家要多思考,多提出疑问,然后结合代码验证自己的结论,如果有意见和建议请评论留言,谢谢