面試問到這個,其實就是讓你說一下binder是干什么的,Service Manager是如何成為一個守護進程的
Binder是干什么的
Binder -- 一種進程間通信(IPC)機制, 基于OpenBinder
- Client、Server和Service Manager實現(xiàn)在用戶空間中,Binder驅(qū)動程序?qū)崿F(xiàn)在內(nèi)核空間中
- Binder驅(qū)動程序和Service Manager在Android平臺中已經(jīng)實現(xiàn),開發(fā)者只需要在用戶空間實現(xiàn)自己的Client和Server
- Binder驅(qū)動程序提供設(shè)備文件/dev/binder與用戶空間交互,Client、Server和Service Manager通過open和ioctl文件操作函數(shù)與Binder驅(qū)動程序進行通信
- Client和Server之間的進程間通信通過Binder驅(qū)動程序間接實現(xiàn)
- Service Manager是一個守護進程,用來管理Server,并向Client提供查詢Server接口的能力
1.Service Manager是如何成為一個守護進程的?即Service Manager是如何告知Binder驅(qū)動程序它是Binder機制的上下文管理者。
Service Manager,它是整個Binder機制的守護進程,用來管理開發(fā)者創(chuàng)建的各種Server,并且向Client提供查詢Server遠程接口的功能
既然Service Manager組件是用來管理Server并且向Client提供查詢Server遠程接口的功能,那么,Service Manager就必然要和Server以及Client進行通信了。我們知道,Service Manger、Client和Server三者分別是運行在獨立的進程當(dāng)中,這樣它們之間的通信也屬于進程間通信了,而且也是采用Binder機制進行進程間通信,因此,Service Manager在充當(dāng)Binder機制的守護進程的角色的同時,也在充當(dāng)Server的角色,然而,它是一種特殊的Server,下面我們將會看到它的特殊之處
Service Manager在用戶空間的源代碼位于frameworks/base/cmds/servicemanager目錄下,主要是由binder.h、binder.c和service_manager.c三個文件組成。Service Manager的入口位于service_manager.c文件中的main函數(shù):
int main(int argc, char **argv)
{
struct binder_state *bs;
void *svcmgr = BINDER_SERVICE_MANAGER;
bs = binder_open(128*1024);
if (binder_become_context_manager(bs)) {
LOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
svcmgr_handle = svcmgr;
binder_loop(bs, svcmgr_handler);
return 0;
}
main函數(shù)主要有三個功能:一是打開Binder設(shè)備文件;二是告訴Binder驅(qū)動程序自己是Binder上下文管理者,即我們前面所說的守護進程;三是進入一個無窮循環(huán),充當(dāng)Server的角色,等待Client的請求
2. Server和Client是如何獲得Service Manager接口的?即defaultServiceManager接口是如何實現(xiàn)的。
ServiceManager 作為守護進程,Service Manager的職責(zé)當(dāng)然就是為Server和Client服務(wù)了。那么,Server和Client如何獲得Service Manager接口,進而享受它提供的服務(wù)呢?
Service Manager在Binder機制中既充當(dāng)守護進程的角色,同時它也充當(dāng)著Server角色,然而它又與一般的Server不一樣。對于普通的Server來說,Client如果想要獲得Server的遠程接口,那么必須通過Service Manager遠程接口提供的getService接口來獲得,這本身就是一個使用Binder機制來進行進程間通信的過程。而對于Service Manager這個Server來說,Client如果想要獲得Service Manager遠程接口,卻不必通過進程間通信機制來獲得,因為Service Manager遠程接口是一個特殊的Binder引用,它的引用句柄一定是0。
經(jīng)過一系列的調(diào)用...
回到defaultServiceManager函數(shù)中,最終結(jié)果為:
gDefaultServiceManager = new BpServiceManager(new BpBinder(0));
這樣,Service Manager遠程接口就創(chuàng)建完成了,它本質(zhì)上是一個BpServiceManager,包含了一個句柄值為0的Binder引用。
在Android系統(tǒng)的Binder機制中,Server和Client拿到這個Service Manager遠程接口之后怎么用呢?
對Server來說,就是調(diào)用IServiceManager::addService這個接口來和Binder驅(qū)動程序交互了,即調(diào)用BpServiceManager::addService 。而BpServiceManager::addService又會調(diào)用通過其基類BpRefBase的成員函數(shù)remote獲得原先創(chuàng)建的BpBinder實例,接著調(diào)用BpBinder::transact成員函數(shù)。在BpBinder::transact函數(shù)中,又會調(diào)用IPCThreadState::transact成員函數(shù),這里就是最終與Binder驅(qū)動程序交互的地方了。回憶一下前面的類圖,IPCThreadState有一個PorcessState類型的成中變量mProcess,而mProcess有一個成員變量mDriverFD,它是設(shè)備文件/dev/binder的打開文件描述符,因此,IPCThreadState就相當(dāng)于間接在擁有了設(shè)備文件/dev/binder的打開文件描述符,于是,便可以與Binder驅(qū)動程序交互了。
對Client來說,就是調(diào)用IServiceManager::getService這個接口來和Binder驅(qū)動程序交互了。具體過程上述Server使用Service Manager的方法是一樣的,這里就不再累述了。