淺談Android系統處理序間通訊(IPC)機制Binder中的Server和Client獲得Service Manager介面之路

來源:互聯網
上載者:User
        在前面一篇文章淺談Service Manager成為Android處理序間通訊(IPC)機制Binder守護進程之路中,介紹了Service Manager是如何成為Binder機制的守護進程的。既然作為守護進程,Service Manager的職責當然就是為Server和Client服務了。那麼,Server和Client如何獲得Service Manager介面,進而享受它提供的服務呢?本文將簡要分析Server和Client獲得Service Manager的過程。

        在閱讀本文之前,希望讀者先閱讀Android處理序間通訊(IPC)機制Binder簡要介紹和學習計劃一文提到的參考資料Android深入淺出之Binder機制,這樣可以加深對本文的理解。

        我們知道,Service Manager在Binder機制中既充當守護進程的角色,同時它也充當著Server角色,然而它又與一般的Server不一樣。對於普通的Server來說,Client如果想要獲得Server的遠程介面,那麼必須通過Service Manager遠程介面提供的getService介面來獲得,這本身就是一個使用Binder機制來進行處理序間通訊的過程。而對於Service Manager這個Server來說,Client如果想要獲得Service Manager遠程介面,卻不必通過處理序間通訊機制來獲得,因為Service Manager遠程介面是一個特殊的Binder引用,它的引用控制代碼一定是0。

        擷取Service Manager遠程介面的函數是defaultServiceManager,這個函式宣告在frameworks/base/include/binder/IServiceManager.h檔案中:

sp<IServiceManager> defaultServiceManager();

       實現在frameworks/base/libs/binder/IServiceManager.cpp檔案中:

sp<IServiceManager> defaultServiceManager(){    if (gDefaultServiceManager != NULL) return gDefaultServiceManager;    {        AutoMutex _l(gDefaultServiceManagerLock);        if (gDefaultServiceManager == NULL) {            gDefaultServiceManager = interface_cast<IServiceManager>(                ProcessState::self()->getContextObject(NULL));        }    }    return gDefaultServiceManager;}

        gDefaultServiceManagerLock和gDefaultServiceManager是全域變數,定義在frameworks/base/libs/binder/Static.cpp檔案中:

Mutex gDefaultServiceManagerLock;sp<IServiceManager> gDefaultServiceManager;

        從這個函數可以看出,gDefaultServiceManager是單例模式,調用defaultServiceManager函數時,如果gDefaultServiceManager已經建立,則直接返回,否則通過interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL))來建立一個,並儲存在gDefaultServiceManager全域變數中。

       在繼續介紹interface_cast<IServiceManager>(ProcessState::self()->getContextObject(NULL))的實現之前,先來看一個類圖,這能夠協助我們瞭解Service Manager遠程介面的建立過程。


        參考資料Android深入淺出之Binder機制一文的讀者,應該會比較容易理解這個圖。這個圖表明了,BpServiceManager類繼承了BpInterface<IServiceManager>類,BpInterface是一個模板類,它定義在frameworks/base/include/binder/IInterface.h檔案中:

template<typename INTERFACE>class BpInterface : public INTERFACE, public BpRefBase{public:BpInterface(const sp<IBinder>& remote);protected:virtual IBinder* onAsBinder();};

        IServiceManager類繼承了IInterface類,而IInterface類和BpRefBase類又分別繼承了RefBase類。在BpRefBase類中,有一個成員變數mRemote,它的類型是IBinder*,實作類別為BpBinder,它表示一個Binder引用,引用控制代碼值儲存在BpBinder類的mHandle成員變數中。BpBinder類通過IPCThreadState類來和Binder驅動程式並互,而IPCThreadState又通過它的成員變數mProcess來開啟/dev/binder裝置檔案,mProcess成員變數的類型為ProcessState。ProcessState類開啟裝置/dev/binder之後,將開啟檔案描述符儲存在mDriverFD成員變數中,以供後續使用。

        理解了這些概念之後,就可以繼續分析建立Service Manager遠程介面的過程了,最終目的是要建立一個BpServiceManager執行個體,並且返回它的IServiceManager介面。建立Service Manager遠程介面主要是下面語句:

            gDefaultServiceManager = interface_cast<IServiceManager>(                ProcessState::self()->getContextObject(NULL));

        看起來簡短,卻暗藏玄機,具體可閱讀Android深入淺出之Binder機制這篇參考資料,這裡作簡要描述。

        首先是調用ProcessState::self函數,self函數是ProcessState的靜態成員函數,它的作用是返回一個全域唯一的ProcessState執行個體變數,就是單例模式了,這個變數名為gProcess。如果gProcess尚未建立,就會執行建立操作,在ProcessState的建構函式中,會通過open檔案操作函數開啟裝置檔案/dev/binder,並且返回來的裝置檔案描述符儲存在成員變數mDriverFD中。

        接著調用gProcess->getContextObject函數來獲得一個控制代碼值為0的Binder引用,即BpBinder了,於是建立Service Manager遠程介面的語句可以簡化為:

            gDefaultServiceManager = interface_cast<IServiceManager>(new BpBinder(0));

        再來看函數interface_cast<IServiceManager>的實現,它是一個模板函數,定義在framework/base/include/binder/IInterface.h檔案中:

template<typename INTERFACE>inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj){    return INTERFACE::asInterface(obj);}

        這裡的INTERFACE是IServiceManager,於是調用了IServiceManager::asInterface函數。IServiceManager::asInterface是通過DECLARE_META_INTERFACE(ServiceManager)宏在IServiceManager類中聲明的,它位於framework/base/include/binder/IServiceManager.h檔案中:

DECLARE_META_INTERFACE(ServiceManager);

        展開即為:

#define DECLARE_META_INTERFACE(ServiceManager)                              \static const android::String16 descriptor;                          \static android::sp<IServiceManager> asInterface(                    \const android::sp<android::IBinder>& obj);                          \virtual const android::String16& getInterfaceDescriptor() const;    \IServiceManager();                                                  \virtual ~IServiceManager();                                         

       IServiceManager::asInterface的實現是通過IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager")宏定義的,它位於framework/base/libs/binder/IServiceManager.cpp檔案中:

IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");

       展開即為:

#define IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager")                 \const android::String16 IServiceManager::descriptor("android.os.IServiceManager");     \const android::String16&       \IServiceManager::getInterfaceDescriptor() const {                                      \return IServiceManager::descriptor;                                                    \}                                                                                      \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);                                                      \}                                                                                      \}                                                                                      \return intr;                                                                           \}                                                                                      \IServiceManager::IServiceManager() { }                                                 \IServiceManager::~IServiceManager() { }      

         估計寫這段代碼的員工是從Microsoft跳槽到Google的。這裡我們關注IServiceManager::asInterface的實現:

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);                                        }                                          }return intr;                                  }   

         這裡傳進來的參數obj就則剛才建立的new BpBinder(0)了,BpBinder類中的成員函數queryLocalInterface繼承自基類IBinder,IBinder::queryLocalInterface函數位於framework/base/libs/binder/Binder.cpp檔案中:

sp<IInterface>  IBinder::queryLocalInterface(const String16& descriptor){    return NULL;}

         由此可見,在IServiceManager::asInterface函數中,最終會調用下面語句:

intr = new BpServiceManager(obj); 

         即為:

intr = new BpServiceManager(new BpBinder(0)); 

        回到defaultServiceManager函數中,最終結果為:

gDefaultServiceManager = new BpServiceManager(new BpBinder(0));

        這樣,Service Manager遠程介面就建立完成了,它本質上是一個BpServiceManager,包含了一個控制代碼值為0的Binder引用。

        在Android系統的Binder機制中,Server和Client拿到這個Service Manager遠程介面之後怎麼用呢?

        對Server來說,就是調用IServiceManager::addService這個介面來和Binder驅動程式互動了,即調用BpServiceManager::addService 。而BpServiceManager::addService又會調用通過其基類BpRefBase的成員函數remote獲得原先建立的BpBinder執行個體,接著調用BpBinder::transact成員函數。在BpBinder::transact函數中,又會調用IPCThreadState::transact成員函數,這裡就是最終與Binder驅動程式互動的地方了。回憶一下前面的類圖,IPCThreadState有一個PorcessState類型的成中變數mProcess,而mProcess有一個成員變數mDriverFD,它是裝置檔案/dev/binder的開啟檔案描述符,因此,IPCThreadState就相當於間接在擁有了裝置檔案/dev/binder的開啟檔案描述符,於是,便可以與Binder驅動程式互動了。

       對Client來說,就是調用IServiceManager::getService這個介面來和Binder驅動程式互動了。具體過程上述Server使用Service Manager的方法是一樣的,這裡就不再累述了。

      IServiceManager::addService和IServiceManager::getService這兩個函數的具體實現,在下面兩篇文章中,會深入到Binder驅動程式這一層,進行詳細的原始碼分析,以便更好地理解Binder處理序間通訊機制,敬請關注。

老羅的新浪微博:http://weibo.com/shengyangluo,歡迎關注!

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.