本文首發(fā)于微信公眾號「后廠技術(shù)官」
前言
在上一篇文章中睦尽,我們了解了學(xué)習(xí)Binder前必須要了解的知識點荆隘,其中有一點就是Binder機制的三個部分: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進程間的通信的使用是很普遍的,在Android進階三部曲第一部的最后一章,我講解了MediaPlayer框架壕曼,這個框架基于C/S架構(gòu)月褥,并采用Binder來進行進程間通信,如下圖所示屯曹。
從圖中可以看出狱庇,除了常規(guī)C/S架構(gòu)的Client端和Server端,還包括了ServiceManager是牢,它用于管理系統(tǒng)中的服務(wù)僵井。
首先Server進程會注冊一些Service到ServiceManager中,Client要使用某個Service驳棱,則需要先到ServiceManager查詢Service的相關(guān)信息批什,然后根據(jù)Service的相關(guān)信息與Service所在的Server進程建立通信通路,這樣Client就可以使用Service了社搅。
2.MediaServer的main函數(shù)
Client驻债、Server、ServiceManager三者的交互都是基于Binder通信的形葬,那么任意兩者的交互都可以說明Binder的通信的原理合呐,可以說Native Binder的原理的核心就是ServiceManager的原理,為了更好的了解ServiceManager笙以,這里拿MediaPlayer框架來舉例淌实,它也是學(xué)習(xí)多媒體時必須要掌握的知識點。
MediaPlayer框架的簡單框架圖如下所示猖腕。
可以看到拆祈,MediaPlayer和MediaPlayerService是通過Binder來進行通信的,MediaPlayer是Client端倘感,MediaPlayerService是Server端放坏,MediaPlayerService是系統(tǒng)多媒體服務(wù)的一種,系統(tǒng)多媒體服務(wù)是由一個叫做MediaServer的服務(wù)進程提供的老玛,它是一個可執(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,其他進程就可以和當(dāng)前的ServiceManager進行交互威根,這里就用到了Binder通信凤巨。
注釋3處用來注冊MediaPlayerService。
除了注釋3處的知識點在下一篇文章進行介紹洛搀,注釋1和注釋2處的內(nèi)容敢茁,本篇文章會分別來進行介紹,先看ProcessState實例留美。
3.每個進程唯一的ProcessState
ProcessState從名稱就可以看出來彰檬,用于代表進程的狀態(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;
}
這里采用了單例模式逢倍,確保每個進程只有一個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è)備進行內(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è)備進行參數(shù)的傳遞,這里的ioctl函數(shù)用于設(shè)定binder支持的最大線程數(shù)為15(maxThreads的值為15)繁涂。最終open_driver函數(shù)返回文件操作符fd拱她。
ProcessState就分析倒這里,總的來說它做了以下幾個重要的事:
1.打開/dev/binder設(shè)備并設(shè)定Binder最大的支持線程數(shù)扔罪。
2.通過mmap為binder分配一塊虛擬地址空間秉沼,達到內(nèi)存映射的目的。
4.ServiceManager中的Binder機制
回到第一小節(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是一個資源標識百匆。注釋1處查詢這個資源標識對應(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負責(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"父款,進行替換后的代碼如下所示。
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)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(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ù)钥勋,還有程序員成長類文章。