本文首發(fā)于微信公眾號「后廠技術(shù)官」
前言
在上一篇文章中,我們了解了學(xué)習(xí)Binder前必須要了解的知識點,其中有一點就是Binder機(jī)制的三個部分:Java Binder、Native Binder、Kernel Binder,其中Java Binder和Native Binder都是應(yīng)用開發(fā)需要掌握的。Java Binder是需要借助Native Binder來工作的,因此需要先了解Native Binder,Native Binder架構(gòu)的原型就是基于Binder通信的C/S架構(gòu),因此我們先從它開始入手。源碼是基于Android 9.0。
1.基于Binder通信的C/S架構(gòu)
在Android系統(tǒng)中,Binder進(jìn)程間的通信的使用是很普遍的,在Android進(jìn)階三部曲第一部的最后一章,我講解了MediaPlayer框架,這個框架基于C/S架構(gòu),并采用Binder來進(jìn)行進(jìn)程間通信,如下圖所示。
從圖中可以看出,除了常規(guī)C/S架構(gòu)的Client端和Server端,還包括了ServiceManager,它用于管理系統(tǒng)中的服務(wù)。
首先Server進(jìn)程會注冊一些Service到ServiceManager中,Client要使用某個Service,則需要先到ServiceManager查詢Service的相關(guān)信息,然后根據(jù)Service的相關(guān)信息與Service所在的Server進(jìn)程建立通信通路,這樣Client就可以使用Service了。
2.MediaServer的main函數(shù)
Client、Server、ServiceManager三者的交互都是基于Binder通信的,那么任意兩者的交互都可以說明Binder的通信的原理,可以說Native Binder的原理的核心就是ServiceManager的原理,為了更好的了解ServiceManager,這里拿MediaPlayer框架來舉例,它也是學(xué)習(xí)多媒體時必須要掌握的知識點。
MediaPlayer框架的簡單框架圖如下所示。
可以看到,MediaPlayer和MediaPlayerService是通過Binder來進(jìn)行通信的,MediaPlayer是Client端,MediaPlayerService是Server端,MediaPlayerService是系統(tǒng)多媒體服務(wù)的一種,系統(tǒng)多媒體服務(wù)是由一個叫做MediaServer的服務(wù)進(jìn)程提供的,它是一個可執(zhí)行程序,在Android系統(tǒng)啟動時,MediaServer也被啟動,它的入口函數(shù)如下所示。
frameworks/av/media/mediaserver/main_mediaserver.cpp
int main(int argc __unused, char **argv __unused)
{
signal(SIGPIPE, SIG_IGN);
//獲取ProcessState實例
sp<ProcessState> proc(ProcessState::self());//1
sp<IServiceManager> sm(defaultServiceManager());//2
ALOGI("ServiceManager: %p", sm.get());
InitializeIcuOrDie();
//注冊MediaPlayerService
MediaPlayerService::instantiate();//3
ResourceManagerService::instantiate();
registerExtensions();
//啟動Binder線程池
ProcessState::self()->startThreadPool();
//當(dāng)前線程加入到線程池
IPCThreadState::self()->joinThreadPool();
}
注釋1處用于獲取ProcessState實例,在這一過程中會打開/dev/binder設(shè)備,并使用mmap為Binder驅(qū)動分配一個虛擬地址空間用來接收數(shù)據(jù)。
注釋2處用來得到一個IServiceManager,通過這個IServiceManager,其他進(jìn)程就可以和當(dāng)前的ServiceManager進(jìn)行交互,這里就用到了Binder通信。
注釋3處用來注冊MediaPlayerService。
除了注釋3處的知識點在下一篇文章進(jìn)行介紹,注釋1和注釋2處的內(nèi)容,本篇文章會分別來進(jìn)行介紹,先看ProcessState實例。
3.每個進(jìn)程唯一的ProcessState
ProcessState從名稱就可以看出來,用于代表進(jìn)程的狀態(tài),先來查看上一小節(jié)的ProcessState的self函數(shù)。
frameworks/native/libs/binder/ProcessState.cpp
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
return gProcess;
}
gProcess = new ProcessState("/dev/binder");//1
return gProcess;
}
這里采用了單例模式,確保每個進(jìn)程只有一個ProcessState實例。注釋1處用于創(chuàng)建一個ProcessState實例,參數(shù)為/dev/binder。接著來查看ProcessState的構(gòu)造函數(shù),代碼如下所示。
frameworks/native/libs/binder/ProcessState.cpp
ProcessState::ProcessState(const char *driver)
: mDriverName(String8(driver))
, mDriverFD(open_driver(driver))//1
, 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) {
mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);//2
if (mVMStart == MAP_FAILED) {
// *sigh*
ALOGE("Using %s failed: unable to mmap transaction memory.\n", mDriverName.c_str());
close(mDriverFD);
mDriverFD = -1;
mDriverName.clear();
}
}
LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating.");
}
ProcessState的構(gòu)造函數(shù)中調(diào)用了很多函數(shù),需要注意的是注釋1處,它用來打開/dev/binder設(shè)備。
注釋2處的mmap函數(shù),它會在內(nèi)核虛擬地址空間中申請一塊與用戶虛擬內(nèi)存相同大小的內(nèi)存,然后再申請物理內(nèi)存,將同一塊物理內(nèi)存分別映射到內(nèi)核虛擬地址空間和用戶虛擬內(nèi)存空間,實現(xiàn)了內(nèi)核虛擬地址空間和用戶虛擬內(nèi)存空間的數(shù)據(jù)同步操作,也就是內(nèi)存映射。
mmap函數(shù)用于對Binder設(shè)備進(jìn)行內(nèi)存映射,除了它還有open、ioctl函數(shù),來看看它們做了什么。
注釋1處的open_driver函數(shù)的代碼如下所示。
frameworks/native/libs/binder/ProcessState.cpp
static int open_driver(const char *driver)
{
int fd = open(driver, O_RDWR | O_CLOEXEC);//1
if (fd >= 0) {
...
size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);//2
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;
}
注釋1處用于打開/dev/binder設(shè)備并返回文件操作符fd,這樣就可以操作內(nèi)核的Binder驅(qū)動了。注釋2處的ioctl函數(shù)的作用就是和Binder設(shè)備進(jìn)行參數(shù)的傳遞,這里的ioctl函數(shù)用于設(shè)定binder支持的最大線程數(shù)為15(maxThreads的值為15)。最終open_driver函數(shù)返回文件操作符fd。
ProcessState就分析倒這里,總的來說它做了以下幾個重要的事:
1.打開/dev/binder設(shè)備并設(shè)定Binder最大的支持線程數(shù)。
2.通過mmap為binder分配一塊虛擬地址空間,達(dá)到內(nèi)存映射的目的。
4.ServiceManager中的Binder機(jī)制
回到第一小節(jié)的MediaServer的入口函數(shù),在注釋2處調(diào)用了defaultServiceManager函數(shù)。
frameworks/native/libs/binder/IServiceManager.cpp
sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
while (gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));//1
if (gDefaultServiceManager == NULL)
sleep(1);
}
}
return gDefaultServiceManager;
}
從IServiceManager所在的文件路徑就可以知道,ServiceManager中不僅僅使用了Binder通信,它自身也是屬于Binder體系的。defaultServiceManager中同樣使用了單例,注釋1處的interface_cast函數(shù)生成了gDefaultServiceManager,其內(nèi)部調(diào)用了ProcessState的getContextObject函數(shù),代碼如下所示。
frameworks/native/libs/binder/ProcessState.cpp
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
return getStrongProxyForHandle(0);
}
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);//1
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 = BpBinder::create(handle);//2
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
getContextObject函數(shù)中直接調(diào)用了getStrongProxyForHandle函數(shù),注意它的參數(shù)的值為0,那么handle的值就為0,handle是一個資源標(biāo)識。注釋1處查詢這個資源標(biāo)識對應(yīng)的資源(handle_entry)是否存在,如果不存在就會在注釋2處新建BpBinder,并在注釋3處賦值給 handle_entry的binder。最終返回的result的值為BpBinder。
4.1 BpBinder和BBinder
說到BpBinder,不得不提到BBinder,它們是Binder通信的“雙子星”,都繼承了IBinder。BpBinder是Client端與Server交互的代理類,而BBinder則代表了Server端。BpBinder和BBinder是一一對應(yīng)的,BpBinder會通過handle來找到對應(yīng)的BBinder。
我們知道在ServiceManager中創(chuàng)建了BpBinder,通過handle(值為0)可以找到對應(yīng)的BBinder。
分析完了ProcessState的getContextObject函數(shù),回到interface_cast函數(shù):
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
interface_cast具體實現(xiàn)如下所示。
frameworks/native/libs/binder/include/binder/IInterface.h
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
當(dāng)前的場景中,INTERFACE的值為IServiceManager,那么替換后代碼如下所示。
inline sp<IServiceManager> interface_cast(const sp<IBinder>& obj)
{
return IServiceManager::asInterface(obj);
}
我們接著來分析IServiceManager。
4.2 解密IServiceManager
BpBinder和BBinder負(fù)責(zé)Binder的通信,而IServiceManager用于處理ServiceManager的業(yè)務(wù),IServiceManager是C++代碼,因此它的定義在IServiceManager.h中。
frameworks/native/libs/binder/include/binder/IServiceManager.h
class IServiceManager : public IInterface
{
public:
DECLARE_META_INTERFACE(ServiceManager)//1
...
//一些操作Service的函數(shù)
virtual sp<IBinder> getService( const String16& name) const = 0;
virtual sp<IBinder> checkService( const String16& name) const = 0;
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated = false,
int dumpsysFlags = DUMP_FLAG_PRIORITY_DEFAULT) = 0;
virtual Vector<String16> listServices(int dumpsysFlags = DUMP_FLAG_PRIORITY_ALL) = 0;
enum {
GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
CHECK_SERVICE_TRANSACTION,
ADD_SERVICE_TRANSACTION,
LIST_SERVICES_TRANSACTION,
};
};
可以看到IServiceManager繼承了IInterface,其內(nèi)部定義了一些常量和一些操作Service的函數(shù),在注釋1處調(diào)用了DECLARE_META_INTERFACE宏,它的定義在IInterface.h中。
frameworks/native/libs/binder/include/binder/IInterface.h
#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();
其中INTERFACE的值為ServiceManager,那么經(jīng)過替換后的代碼如下所示。
static const ::android::String16 descriptor;
//定義asInterface函數(shù)
static ::android::sp<IServiceManager> asInterface(
const ::android::sp<::android::IBinder>& obj);
virtual const ::android::String16& getInterfaceDescriptor() const;
//定義IServiceManager構(gòu)造函數(shù)
IServiceManager();
//定義IServiceManager析構(gòu)函數(shù)
virtual ~IServiceManager();
從DECLARE_META_INTERFACE宏的名稱和上面的代碼中,可以發(fā)現(xiàn)它主要聲明了一些函數(shù)和一個變量。那么這些函數(shù)和變量的實現(xiàn)在哪呢?答案還是在IInterface.h中,叫做IMPLEMENT_META_INTERFACE宏,代碼如下所示/
frameworks/native/libs/binder/include/binder/IInterface.h
#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() { } \
DECLARE_META_INTERFACE宏和IMPLEMENT_META_INTERFACE宏是配合使用的,很多系統(tǒng)服務(wù)都使用了它們,IServiceManager使用IMPLEMENT_META_INTERFACE宏只有一行代碼,如下所示。
frameworks/native/libs/binder/IServiceManager.cpp
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
IMPLEMENT_META_INTERFACE宏的INTERFACE值為ServiceManager,NAME值為"android.os.IServiceManager",進(jìn)行替換后的代碼如下所示。
const ::android::String16 IServiceManager::descriptor("android.os.IServiceManager");
const ::android::String16&
IServiceManager::getInterfaceDescriptor() const {
return IServiceManager::descriptor;
}
//實現(xiàn)了asInterface函數(shù)
::android::sp<IServiceManager> IServiceManager::asInterface(
const ::android::sp<::android::IBinder>& obj)
{
::android::sp<IServiceManager> intr;
if (obj != NULL) {
intr = static_cast<IServiceManager>(
obj->queryLocalInterface(
IServiceManager::descriptor).get());
if (intr == NULL) {
intr = new BpServiceManager(obj);//1
}
}
return intr;
}
IServiceManager::IServiceManager() { }
IServiceManager::~IServiceManager() { }
關(guān)鍵的點就在于注釋1處,新建了一個BpServiceManager,傳入的參數(shù)obj的值為BpBinder。看到這里,我們也就明白了,asInterface函數(shù)就是用BpBinder為參數(shù)創(chuàng)建了BpServiceManager,從而推斷出interface_cast函數(shù)創(chuàng)建了BpServiceManager,再往上推斷,IServiceManager的defaultServiceManager函數(shù)返回的就是BpServiceManager。
BpServiceManager有什么作用呢,先從BpServiceManager的構(gòu)造函數(shù)看起。
frameworks/native/libs/binder/IServiceManager.cpp
class BpServiceManager : public BpInterface<IServiceManager>
{
public:
explicit BpServiceManager(const sp<IBinder>& impl)
: BpInterface<IServiceManager>(impl)
{
}
...
}
impl的值其實就是BpBinder,BpServiceManager的構(gòu)造函數(shù)調(diào)用了基類BpInterface的構(gòu)造函數(shù)。
frameworks/native/libs/binder/include/binder/IInterface.h
template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase
{
...
};
BpInterface繼承了BpRefBase,BpRefBase的實現(xiàn)如下所示。
frameworks/native/libs/binder/Binder.cpp
BpRefBase::BpRefBase(const sp<IBinder>& o)
: mRemote(o.get()), mRefs(NULL), mState(0)
{
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
if (mRemote) {
mRemote->incStrong(this);
mRefs = mRemote->createWeak(this);
}
}
mRemote是一個IBinder* 指針,它最終的指向為BpBinder,也就是說BpServiceManager的mRemote指向了BpBinder。那么BpServiceManager的作用也就知道了,就是它實現(xiàn)了IServiceManager,并且通過BpBinder來實現(xiàn)通信。
4.3 IServiceManager家族
可能上面講的會讓你有些頭暈,這是因為對各個類的關(guān)系不大明確,通過下圖也許你就會豁然開朗。
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機(jī)制,建議將圖片保存下來直接上傳(img-4HtEwN0A-1578825026363)(https://s2.ax1x.com/2019/10/08/ufWhRI.png)]
1.BpBinder和BBinder都和通信有關(guān),它們都繼承自IBinder。
2.BpServiceManager派生自IServiceManager,它們都和業(yè)務(wù)有關(guān)。
3.BpRefBase包含了mRemote,通過不斷的派生,BpServiceManager也同樣包含mRemote,它指向了BpBinder,通過BpBinder來實現(xiàn)通信。
5.小節(jié)
本篇文章我們學(xué)到了Binder通信的C/S架構(gòu),也知道了Native Binder的原理的核心其實就是ServiceManager的原理,為了講解ServiceManager的原理,我們需要一個框架來舉例,那就是MediaPlayer框架。在講解MediaServer的入口函數(shù)時,我們遇到了三個問題,其中前兩個問題相關(guān)的知識點ProcessState和IServiceManager都講解到了,下一篇文章會講解第三個問題,MediaPlayerService是如何注冊的。
更多的見我的原創(chuàng)知識體系:
https://github.com/henrymorgen/android-knowledge-system
這里不僅分享大前端、Android、Java等技術(shù),還有程序員成長類文章。
