提示:源码android7.1
这篇文章我会讲解一下c++层的binder架构,我会把我知道的重要知识点都讲出来,希望对binder不太熟悉的朋友有些许帮助。
先列举一下我会说到的文件,讲到该文件时我就不再列举路径了:
framework/native/include/binder/IBinder.h
framework/native/include/binder/Binder.h
framework/native/include/binder/IInterface.h
framework/native/include/binder/BpBinder.h
framework/native/include/binder/IPCThreadState.h
framework/native/include/binder/IServiceManager.h
framework/native/include/binder/ProcessState.h
framework/native/libs/binder/Binder.cpp
framework/native/libs/binder/BpBinder.cpp
framework/native/libs/binder/IInterface.cpp
framework/native/libs/binder/IPCThreadState.cpp
framework/native/libs/binder/ProcessState.cpp
framework/native/libs/binder/IServiceManager.cpp
下面我先给出一张图:
RefBase从字面上是“引用基类”的意思,为什么它在金字塔的顶层了。
这里我要科普一下,看过Android源码中的c++代码,一定不会对sp/wp感到陌生,系统中有大量的sp/wp,在android系统中,通过RefBase,sp(strong pointer)/wp(weak pointer)这一系列强弱引用计数(也可以叫智能指针),可以实现对对象生命周期的管理。
它们所在的文件如下:
system/core/libutils/RefBase.cpp
system/core/include/utils/RefBase.h
system/core/include/utils/StrongPointer.h
使用引用计数的原因有2个:1是为了防止内存泄露,2是为了避免野指针。
如何使用引用计数,假设现在有一个类,如果要用智能指针来引用这个类的对象,必须满足一下2点:
(1)这个类必须是基类RefBase的子类或者间接子类。
(2)这个类必须定义虚析构函数,比如:virtual ~myClass();
RefBase就讲这么多了,毕竟它不是我们关注的重点,回到binder的分析,这张图里的类都很重要,里面有的类里含有xxx,这是要我们自己去定义的,比如xxx=myService,替代进去就可以了。
我这里要借鉴刘超大神的书中所说把binder涉及到的对象进行一下分类,便于下面的讲解:
(1)Binder实体对象:Binder实体对象就是Binder服务的提供者,”Binder实体对象“对应的是“BBinder 对象"
(2)Binder引用对象:Binder引用对象是Binder实体对象在客户端进程的代表,每个引用对象的类型都是BpBinder类,以名称”BpBinder 对象“来代替”Binder引用对象“
(3)Binder代理对象:也可以叫做Binder接口对象,它主要是为客户端的上层应用提供接口服务,从IInterface派生,它实现Binder服务的函数接口,当然只是一个转掉的空壳,通过代理对象,应用能像使用本地对象一样使用远端的实体对象提供的服务。
(4)IBinder对象,BBinder和BpBinder都是从IBinder类派生,其实不用刻意的去区分引用对象和实体对象,可以用”IBinder“来统一称呼。
这里我把我文章的讲解的内容这里梳理一下:
1.讲解一下binder的大致框架
2.讲解一下server和client获得servicemanager接口的过程
3.提一下java层的BinderService
1》讲一下binder的大体框架
1,IBinder,BBinder,BpBinder
在c++层次我们就能看到binder的主要一些核心类了,BBinder和BpBinder都由IBinder派生,下面我把IBinder.h的部分内容贴出来:
class IBinder : public virtual RefBase
{
public:
enum {
FIRST_CALL_TRANSACTION = 0x00000001,
LAST_CALL_TRANSACTION = 0x00ffffff,
PING_TRANSACTION = B_PACK_CHARS('_','P','N','G'),
DUMP_TRANSACTION = B_PACK_CHARS('_','D','M','P'),
SHELL_COMMAND_TRANSACTION = B_PACK_CHARS('_','C','M','D'),
INTERFACE_TRANSACTION = B_PACK_CHARS('_', 'N', 'T', 'F'),
SYSPROPS_TRANSACTION = B_PACK_CHARS('_', 'S', 'P', 'R'),
// Corresponds to TF_ONE_WAY -- an asynchronous call.
FLAG_ONEWAY = 0x00000001
};
IBinder();
/**
* Check if this IBinder implements the interface named by
* @a descriptor. If it does, the base pointer to it is returned,
* which you can safely static_cast<> to the concrete C++ interface.
*/
virtual sp queryLocalInterface(const String16& descriptor);
/**
* Return the canonical name of the interface provided by this IBinder
* object.
*/
virtual const String16& getInterfaceDescriptor() const = 0;
virtual bool isBinderAlive() const = 0;
virtual status_t pingBinder() = 0;
virtual status_t dump(int fd, const Vector& args) = 0;
static status_t shellCommand(const sp& target, int in, int out, int err,
Vector& args,
const sp& 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& who) = 0;
};
/**
* Register the @a recipient for a notification if this binder
* goes away. If this binder object unexpectedly goes away
* (typically because its hosting process has been killed),
* then DeathRecipient::binderDied() will be called with a reference
* to this.
*
* The @a cookie is optional -- if non-NULL, it should be a
* memory address that you own (that is, you know it is unique).
*
* @note You will only receive death notifications for remote binders,
* as local binders by definition can't die without you dying as well.
* Trying to use this function on a local binder will result in an
* INVALID_OPERATION code being returned and nothing happening.
*
* @note This link always holds a weak reference to its recipient.
*
* @note You will only receive a weak reference to the dead
* binder. You should not try to promote this to a strong reference.
* (Nor should you need to, as there is nothing useful you can
* directly do with it now that it has passed on.)
*/
virtual status_t linkToDeath(const sp& recipient,
void* cookie = NULL,
uint32_t flags = 0) = 0;
/**
* Remove a previously registered death notification.
* The @a recipient will no longer be called if this object
* dies. The @a cookie is optional. If non-NULL, you can
* supply a NULL @a recipient, and the recipient previously
* added with that cookie will be unlinked.
*/
virtual status_t unlinkToDeath( const wp& recipient,
void* cookie = NULL,
uint32_t flags = 0,
wp* 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:
};
我们看到在IBinder中有很多纯虚函数,也就是说IBinder是一个抽象类,是不能实例化的,所以必须要有派生类,而BBinder和BpBinder就出现了,它两都继承了IBInder,并且把这些纯虚函数都重写了,所以BBinder和BpBinder是可以实例化的,这里还要注意IBinder是可以使用应用计数的,也就是用智能指针来管理它的对象,也就是BpBinder和BBinder的对象。这里有两个函数,localBinder和remoteBinder,用它们可以得到BBinder和BpBinder,看函数意思也知道,一个得到本地实体对象,一个是得到引用对象。
2.IInterface,BnInterface,BpInterface
下面介绍一下IInterface以及他的两个派生类:BnInterface和BpInterface
首先看一下Interface.h,节选一些代码贴出来:
class IInterface : public virtual RefBase
{
public:
IInterface();
static sp asBinder(const IInterface*);
static sp asBinder(const sp&);
protected:
virtual ~IInterface();
virtual IBinder* onAsBinder() = 0;
};
// ----------------------------------------------------------------------
template
inline sp interface_cast(const sp& obj)
{
return INTERFACE::asInterface(obj);
}
template
class BnInterface : public INTERFACE, public BBinder
{
public:
virtual sp queryLocalInterface(const String16& _descriptor);
virtual const String16& getInterfaceDescriptor() const;
protected:
virtual IBinder* onAsBinder();
};
// ----------------------------------------------------------------------
template
class BpInterface : public INTERFACE, public BpRefBase
{
public:
BpInterface(const sp& remote);
protected:
virtual IBinder* onAsBinder();
};
#define DECLARE_META_INTERFACE(INTERFACE) \
static const android::String16 descriptor; \
static android::sp asInterface( \
const android::sp& obj); \
virtual const android::String16& getInterfaceDescriptor() const; \
I##INTERFACE(); \
virtual ~I##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::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() { }
......
template
inline IBinder* BpInterface::onAsBinder()
{
return remote();
}
......
这里不同的是BnInterface它还继承与BBinder,而BpInterface另一个继承对象为BpRefBase,这里为什么要这样设计了,先看一下BpRefbase
class BpRefBase : public virtual RefBase
{
protected:
BpRefBase(const sp& 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 mState;
};
我们看到在BpRefBase内部是有一个mRemote成员的,它是一个指向IBinder的指针。因为BpInterface继承了BpRefBase,所以BpInterface先天就内置了一个
mRemote成员,
在实际的开发中,我们完全可以创建多个聚合同一BpBinder的代理对象,这个代理对象其实对应着同一个远端binder实体,用户可以创建很多个代理对象(也叫代理接口)也意为着方便了用户的使用。
在编写c++层的binder时,BpInterface和BnInterface都是用户需要去继承的类,它们是代理对象,也是直接交互的对象。
3,DECLARE_META_INTERFACE,IMPLEMENT_META_INTERFACE
下面我要提一下2个重要的宏,android巧妙的通过DECLARE_META_INTERFACE(INTERFACE)和IMPLEMENT_META_INTERFACE(INTERFACE, NAME) 将通信和业务牢牢的栓在了一起。这2个宏我刚才已经贴出来了,也是在IInterface.h中。这里只有告你大家这2个宏很重要,具体的分析在下面我会讲到。
4,ProcessState
每个进程只有一个ProcessState,它是独一无二的,ProcessState的字面意思就是进程状态,来看下ProcessState的定义,在ProcessState.h中
class ProcessState : public virtual RefBase
{
public:
static sp self();
void setContextObject(const sp& object);
sp getContextObject(const sp& caller);
void setContextObject(const sp& object,
const String16& name);
sp getContextObject(const String16& name,
const sp& caller);
void startThreadPool();
typedef bool (*context_check_func)(const String16& name,
const sp& caller,
void* userData);
bool isContextManager(void) const;
bool becomeContextManager(
context_check_func checkFunc,
void* userData);
sp getStrongProxyForHandle(int32_t handle);
wp getWeakProxyForHandle(int32_t handle);
void expungeHandle(int32_t handle, IBinder* binder);
void spawnPooledThread(bool isMain);
status_t setThreadPoolMaxThreadCount(size_t maxThreads);
void giveThreadPoolName();
private:
friend class IPCThreadState;
ProcessState();
~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);
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.
VectormHandleToObject;
bool mManagesContexts;
context_check_func mBinderContextCheckFunc;
void* mBinderContextUserData;
KeyedVector >
mContexts;
String8 mRootDir;
bool mThreadPoolStarted;
volatile int32_t mThreadPoolSeq;
};
ProcessState中有一个mDriverFD,这个值用来记录binder驱动对应的句柄值,以便随时和binder驱动通信,ProcessState采用了单例模式,来看它的ProcessState.cpp:
sp ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
return gProcess;
}
gProcess = new ProcessState;
return gProcess;
}
ProcessState::ProcessState()
: mDriverFD(open_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;
}
}
LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating.");
}
5.IPCThreadState
IPCThreadState和驱动之间耦合的很厉害,BpBinder会和IPCThreadState打交道,然后IPCThreadState就和驱动打交道。我们知道借助友元(friend),可以使得其他类中的成员函数以及全局范围内的函数访问当前类的 private 成员,友元类中的所有成员函数都是另外一个类的友元函数,在上面ProcessState中可以看到,IPCThreadState被声明为了ProcessState的友元类,也就是说IPCThreadState中的所有函数都可以访问ProcessState的private成员。
2》server和client获取servicemanager接口的过程
先看一下servicemanager的关系图,实际上系统中只有Iservicemanager,BpServiceManger,系统中并没有BnServiceManger,那是因为android弄了一个service_manager.c来充当BnServiceManager的角色,在servicemanager篇中我么已经说过这个它的main函数了。
获取servicemanager远程接口的函数是defaultServiceManager,在Iservicemanager..cpp中
sp defaultServiceManager()
{
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
while (gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast(
ProcessState::self()->getContextObject(NULL));
if (gDefaultServiceManager == NULL)
sleep(1);
}
}
return gDefaultServiceManager;
}
从defaultServiceManager函数看出gDefaultServiceManager是单例模式,该函数中最重要的一句就是
gDefaultServiceManager = interface_cast
ProcessState::self()->getContextObject(NULL));
我们仔细分析一下,首先通过ProcessState::self()得到一个ProcessState的单例对象gProcess,ProcessState在创建的时候会通过open函数打开驱动文件/dev/binder/,并且将返回的设备描述符保存在mDriverFD中。然后调用得到的gProcess的getContextObject函数
sp ProcessState::getContextObject(const sp& /*caller*/)
{
return getStrongProxyForHandle(0);
}
继续跟踪getStrongProxyForHandle(0)
sp ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
if (handle == 0) {
Parcel data;
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, NULL, 0);
if (status == DEAD_OBJECT)
return NULL;
}
b = new BpBinder(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
这里生成了BpBInder(0),于是上面的代码变成了gDefaultServiceManager = interface_cast
接着看interface_cast函数,实际上它是一个很重要的类型转换函数,在IInterface.h中,
template
inline sp interface_cast(const sp& obj)
{
return INTERFACE::asInterface(obj);
}
即调用了IServiceManager:asInterface(BpBinder(0));
还记得上面的IMPLEMENT_META_INTERFACE宏吗,该asInterface函数就是在这个宏里面定义的
IServiceManager具体的定义如下
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
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; \
}
这里传进来的obj参数为BpBinder(0),INTERFACE为IServiceManager,
sp IBinder::queryLocalInterface(const String16& /*descriptor*/)
{
return NULL;
}
那么这里intr==null
intr = new BpServiceManager(BpBinder(0))
这样ServiceManager的远程接口就创建完成了,它其实是一个BpServiceManager,包含了一个句柄值为0的BpBinder引用对象
3》其实Binder服务可以分为2种,一种是实名服务,一种是匿名服务,它们从开发到使用没有任何区别,唯一的区别是实名服务可以用servicemanager查找到,如ActivityManagerService,PowerManagerService,匿名服务不能用servicemanager查找到,比如frameworks层提供的一种启动java匿名binder服务的方法:
首先某个应用通过调用binderService方法发出一个intent,Framework根据intent找到对应的组件service并启动它,包含在service中的binder服务也同时创建出来,随后,framework会把服务的IBinder对象通过ConnectivityManager的回调方法onServiceConnected传回到应用,这样应用客户端就得到匿名BInder服务的引用对象,也就能使用组件Service中的匿名BInder服务了,在这里Frameworks中的Intent代替了Binder服务的名称来查找对应的服务,同时也承担了ServiceManager的工作。
参考文献:《深入解析Android5.0系统》;《Android开发艺术探索》;《深入理解Android卷1》;《深入理解Android卷3》;红茶一杯话binder------点击打开链接;gityuan的binder系列------点击打开链接;罗升阳的binder系列------点击打开链接;Andriod Binder机制------点击打开链接;Android深入浅出之binder机制------点击打开链接;理解Android的binder机制-----点击打开链接;轻松理解Androidbinder------点击打开链接;binder service入门------点击打开链接