Binder基本概念流程學習


 

一 Media Service進程啟動

Init.rc中描述的service對應linux 的進程:

Media進程定義:

service media /system/bin/mediaserver class main user media group audio camera inet net_bt net_bt_admin net_bw_acct drmrpc ioprio rt 4

servicemanager 進程定義:

service servicemanager /system/bin/servicemanager class core user system   group system

 

  Media中有很多Native Service(AudioFlinger MediaPlayerService CameraService 
AudioPolicyService等),整個Android(native或者framework)的Service都需要加入
servicemanager中進行統一管理。
  那么Media Process 與ServiceManager Process是如何進行通信的呢——Binder.
通過Media Process中使用binder進行完成IPC過程,學習Binder的概念和使用方法。

\frameworks\av\media\mediaserver\ main_mediaserver.cpp:

int main(int argc, char** argv) { //創建ProcessState 當前進程屬性
    sp<ProcessState> proc(ProcessState::self()); //IServiceManager對象
    sp<IServiceManager> sm = defaultServiceManager(); //初始化MediaPlayerService服務對象
 MediaPlayerService::instantiate(); …… //啟動進程的線程池
    ProcessState::self()->startThreadPool(); //執行線程消息循環
    IPCThreadState::self()->joinThreadPool(); }

  Sp:指針運算符和普通運算符的重載 StrongPointer。

二 Media Process執行過程

1 ProcessState對象創建

當前進程的狀態屬性,對象創建:

sp<ProcessState> ProcessState::self() { Mutex::Autolock _l(gProcessMutex); if (gProcess != NULL) { return gProcess; } gProcess = new ProcessState; return gProcess; }

ProcessState構造函數:

ProcessState::ProcessState() : mDriverFD(open_driver()) //打開binder驅動設備
 , mVMStart(MAP_FAILED) , mManagesContexts(false) , mBinderContextCheckFunc(NULL) , mBinderContextUserData(NULL) , mThreadPoolStarted(false) , mThreadPoolSeq(1) { if (mDriverFD >= 0) { //將binder的fd映射到當前進程虛擬空間地址中 與binder進行交互
        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ,         MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0); } }

打開binder設備:

static int open_driver() { //打開binder設備驅動
    int fd = open("/dev/binder", O_RDWR); if (fd >= 0) { //bidner最大支持線程數
        size_t maxThreads = 15; result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads); } return fd; }

ProcessState對象創建過程所做的事:
  打開/dev/binder設備,得到binder設備的fd;
  將bidner設備fd映射到當前進程虛擬地址空間建立交互的通道;

2 IServiceManager對象創建
  sp<IServiceManager> sm = defaultServiceManager();
為什么需要一個IServiceManager對象呢,這個類是個抽象提供接口

class IServiceManager : public IInterface { virtual sp<IBinder> getService( const String16& name) const = 0; virtual status_t addService( const String16& name, const sp<IBinder>& service, bool allowIsolated = false) = 0; …… };

  通過IServiceManager派生對象操作將Service加入到ServiceManager中.

defaultServiceManager()函數:

sp<IServiceManager> defaultServiceManager() { //單例對象
    if (gDefaultServiceManager != NULL) return gDefaultServiceManager; AutoMutex _l(gDefaultServiceManagerLock); if (gDefaultServiceManager == NULL) { //創建對象
        gDefaultServiceManager = interface_cast<IServiceManager>( ProcessState::self()->getContextObject(NULL)); } return gDefaultServiceManager; } 

ProcessState::self()->getContextObject(NULL):得到一個IBinder對象

  ProcessState::self()剛才所創建的ProcessState對象。

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對應的handle_entry //若沒有則創建一個 handle == 0
    handle_entry* e = lookupHandleLocked(handle); if (e != NULL) { IBinder* b = e->binder; if (b == NULL || !e->refs->attemptIncWeak(this)) { //handle_entry對象成員初始化 創建handle=0的BpBinder 
            b = new BpBinder(handle); e->binder = b; if (b) e->refs = b->getWeakRefs(); result = b; } } return result; }

  handle_entry是什么呢?

      struct handle_entry {
                IBinder* binder;
                RefBase::weakref_type* refs;
            };

  也就是說ProcessState 有一個表Vector<handle_entry>mHandleToObject;

表里面的每一項存儲了一個binder,每一個binder對應一個handle。

  

  Handle = 0是什么,句柄? 代表誰的句柄——ServiceManager在binder中的資源。
從ProcessState::self()->getContextObject(NULL)得到一個 IBinder——BpBinder(0);
於是得到:
  gDefaultServiceManager = interface_cast<IServiceManager>(BpBinder(0));

使用interface_cast將IBinder實例轉化成IServiceManager實例。

3 interface_cast函數

\frameworks\native\include\binder\IInterface.h:

interface_cast是個內聯模板函數: 

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

結合前面就是:

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

 

所以需要到IServiceManager里面去看看是如何實現的

4 IServiceManager類

\frameworks\native\include\binder\IServiceManager.h:

IServiceManager是一個抽象類:

class IServiceManager : public IInterface {   public: //宏聲明
 DECLARE_META_INTERFACE(ServiceManager); virtual sp<IBinder> getService( const String16& name) const = 0; virtual status_t addService( const String16& name, const sp<IBinder>& service, bool allowIsolated = false) = 0; …… }

DECLARE_META_INTERFACE聲明:

#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();                                            \ 

替換成IServiceManager:

//實現時傳入:android.os.IServiceManager
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(); 

實現\frameworks\native\include\binder\IServiceManager.cpp:

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

IMPLEMENT_META_INTERFACE實現:
看一下asInterface接口:

#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \
    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;                                                    \
}                                             \

替換成IServiceManager:

android::sp<IServiceManager> IServiceManager::asInterface( const android::sp<android::IBinder>& obj) { //obj BpBinder實例 
        android::sp<IServiceManager> intr; if (obj != NULL) { //返回NULL 
            intr = static_cast<IServiceManager*>( obj->queryLocalInterface( IServiceManager::descriptor).get()); if (intr == NULL) { intr = new BpServiceManager(obj); } } return intr; }

這里得到IServiceManager 實例:

  BpServiceManager:new BpServiceManager(new BpBinder(0));

5 BpServiceManager 和 BpInterface類

\frameworks\native\libs\binder\ IServiceManager.cpp:BpServiceManager

class BpServiceManager : public BpInterface<IServiceManager> { public: //impl就是 new BpBinder(0)
    BpServiceManager(const sp<IBinder>& impl) : BpInterface<IServiceManager>(impl) { } virtual sp<IBinder> checkService(const String16& name) const { …… remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply); } virtual status_t addService(const String16& name, const sp<IBinder>& service, bool allowIsolated) { …… remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply); } }

\frameworks\native\include\binder\ IInterface.h:模板類BpInterface

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

BpInterface構造函數:

template<typename INTERFACE> inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote) : BpRefBase(remote) {
}

BpRefBase構造函數:

BpRefBase::BpRefBase(const sp<IBinder>& o) : mRemote(o.get()), mRefs(NULL), mState(0) {   // IBinder mRemote 指向 o.get() :new BpBinder(0)
}

  gDefaultServiceManager = interface_cast<IServiceManager>(BpBinder(0));
實際為:
  gDefaultServiceManager = new BpServiceManager(new BpBinder(0));
Bn代表Binder Native Bp代表Binder Proxy
BpServiceManager代理的BpBinder實例 BpBinder代理的handle(0)

這個關系有些復雜,看一下類繼承結構圖:

  


  上面這個結構看起來感覺很熟悉——Bridge模式。將Binder數據交互和功能處理橋接起來。

在Media Process 的main函數中通過:

  sp<IServiceManager> sm = defaultServiceManager();
  我們得到了sm:是BpServiceManager對象。

三 MediaPlayerService加入到ServiceManager中

回到main函數中:

int main(int argc, char** argv) { //創建ProcessState 當前進程屬性
    sp<ProcessState> proc(ProcessState::self()); //IServiceManager對象
    sp<IServiceManager> sm = defaultServiceManager(); //初始化MediaPlayerService服務對象
    MediaPlayerService::instantiate();     //執行到這里
 …… //啟動進程的線程池
    ProcessState::self()->startThreadPool(); //執行線程消息循環
    IPCThreadState::self()->joinThreadPool(); }

1 MediaPlayerService初始化過程

void MediaPlayerService::instantiate() {   // defaultServiceManager就是上面所述得到的BpServiceManager對象
  defaultServiceManager()->addService(     String16("media.player"), new MediaPlayerService()); }

BpServiceManager添加Service:

virtual status_t addService(const String16& name, const sp<IBinder>& service, bool allowIsolated) { //生成數據包Parcel
 Parcel data, reply; // Write RPC headers 寫入Interface名字 得到“android.os.IServiceManager”
 data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); //寫入Service名字 “media.player”
 data.writeString16(name); //寫入服務
 data.writeStrongBinder(service); data.writeInt32(allowIsolated ? 1 : 0); // remote()返回BpBinder對象
        status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply); return err == NO_ERROR ? reply.readExceptionCode() : err; }

remote()->transact 到BpBinder中:

status_t BpBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { if (mAlive) { //到當前進程IPCThreadState中 mHandle=0
        status_t status = IPCThreadState::self()->transact( mHandle, code, data, reply, flags); if (status == DEAD_OBJECT) mAlive = 0; return status; } return DEAD_OBJECT; }

 

2 IPCThreadState中寫入數據到Binder設備過程

IPCThreadState::self()->transact過程:

status_t IPCThreadState::transact(int32_t handle, uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { status_t err = data.errorCheck(); flags |= TF_ACCEPT_FDS; //將數據轉化成binder_transaction_data 寫入到Parcel實例mOut中
    err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL); //寫入數據
    err = waitForResponse(reply); return err; } status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) { while (1) { //將數據寫入到Binder設備中
 talkWithDriver(); …… } return err; } status_t IPCThreadState::talkWithDriver(bool doReceive) { //將數據封裝成binder_write_read結構
 binder_write_read bwr; do { //將數據寫入到所打開的Binder設備中
        ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) …… } while (err == -EINTR); return NO_ERROR; }

  將MediaPlayerService加入到ServiceManager中,

這里就通過BpServiceManager的AddService將數據寫入到Binder設備傳遞給ServiceManager。

繼續Media Process過程

四 Media Process消息循環

int main(int argc, char** argv) { //啟動進程的線程池 
    ProcessState::self()->startThreadPool();     //走到了這里 //執行線程消息循環
    IPCThreadState::self()->joinThreadPool(); }


1 創建工作者線程

startThreadPool:\frameworks\native\libs\binder\ ProcessState.cpp:

void ProcessState::startThreadPool() { spawnPooledThread(true); } void ProcessState::spawnPooledThread(bool isMain) { //創建PoolThread對象 並run ,非線程
    sp<Thread> t = new PoolThread(isMain);   t->run(buf); }

  PoolThread繼承Thread

執行Thread的run函數:

status_t Thread::run(const char* name, int32_t priority, size_t stack) { //創建線程mThread _threadLoop
    bool res; res = createThreadEtc(_threadLoop, this, name, priority, stack, &mThread); return NO_ERROR; }

現在有兩個線程:主線程和mThread線程

mThread線程執行:_threadLoop

int Thread::_threadLoop(void* user) { Thread* const self = static_cast<Thread*>(user); do { //調用子類的threadLoop
        result = self->threadLoop(); …… } while(strong != 0); return 0; } class PoolThread : public Thread { protected: virtual bool threadLoop() { IPCThreadState::self()->joinThreadPool(mIsMain); return false; } };

2 進程間通信消息循環過程

消息循環:

void IPCThreadState::joinThreadPool(bool isMain) { mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER); status_t result; //消息循環
    do { int32_t cmd; //從binder設備中讀取命令
        result = talkWithDriver(); if (result >= NO_ERROR) { cmd = mIn.readInt32(); //執行命令
            result = executeCommand(cmd); } …… } while (result != -ECONNREFUSED && result != -EBADF); mOut.writeInt32(BC_EXIT_LOOPER); talkWithDriver(false); }

命令執行:

status_t IPCThreadState::executeCommand(int32_t cmd) { BBinder* obj; RefBase::weakref_type* refs; switch (cmd) { case BR_DECREFS: break; case BR_ATTEMPT_ACQUIRE: break; case BR_TRANSACTION:   binder_transaction_data tr; result = mIn.read(&tr, sizeof(tr)); if (tr.target.ptr) { //將目標對象轉化成BBinder
        sp<BBinder> b((BBinder*)tr.cookie); //調用BBinder的transact 函數
       const status_t error = b->transact(tr.code, buffer, &reply, tr.flags); } break; …… default: } return result; }

  binder_transaction_data.cookie:target object cookie目標對象,這個target object是指那個呢?

在Media Process里面有幾個Service:AudioFlinger、MediaPlayerService、CameraService等。

這個目標是這其中Service中的一個,假設目標對象為為MediaPlayerService,那為何要轉化成BBinder呢?

3 Service對命令的處理

  線程從binder接收到消息命令,將命令傳遞給Service處理。將目標對象轉化成BBinder,然后調度此命令;

命令從遠端傳遞到本地端進行處理,每個Service都對應BnXXX對象來處理遠端BpXXX傳來的命令。
  sp<BBinder> b((BBinder*)tr.cookie);
  const status_t error = b->transact(tr.code, buffer, &reply, tr.flags);
  這里b代表某個Service:假設為MediaPlayerService;弄清楚執行過程,要弄清楚類繼承關系。

    


  本地端BnMediaPlayerService消息處理過程:真正的對象是MediaPlayerService實例。
從BBinder ->transact開始傳遞:

status_t BBinder::transact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { //onTransact是個virtual函數 派生類BnMediaPlayerService重寫
    err = onTransact(code, data, reply, flags); return err; } status_t BnMediaPlayerService::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch (code) { case CREATE: { pid_t pid = data.readInt32(); sp<IMediaPlayerClient> client = interface_cast<IMediaPlayerClient>(data.readStrongBinder()); //create是個virtual函數 派生類MediaPlayerService重寫
            sp<IMediaPlayer> player = create(pid, client, audioSessionId); //創建player寫入到數據包中 傳回
            reply->writeStrongBinder(player->asBinder()); return NO_ERROR; } break; …… default: return BBinder::onTransact(code, data, reply, flags); } }

 

可以看看Client類繼承關系結構圖:

    

  看到這個跟上面的MediaPlayerService繼承關系非常的相似,

  這個結構也非常的熟悉——Adapter模式;將binder消息交互和命令處理適配到一起。

五 Client端與Service端交互

  Client對Service進行使用Binder通信,是得到一個Service BnXXX端對象的代理,在Client 為BpXXX代理,

然后使用此代理進行相關的操作. 前面在使用ServiceManager就是此種方式進行。

  實際上通信的基礎是Binder,Proxy不過是在Binder上進行了一層封裝,封裝了對binder驅動的底層操作,使具有面向對象的特性。

任意兩個進程通過Binder進行通信,就是先得到另一個進程的binder標識,通過此binder進行數據交換。

    

1 新增加一個服務
看下面media Palyer類繼承結構。
實現Bn端類繼承結構:

    


實現Bp端類繼承結構

    

 

可以看到 :

  •   需要定義服務公共接口IMediaPlayerService;
  •   實現服務Bn端 派發消息BnMediaPlayerService;
  •   實現服務的命令處理MediaPlayerService;
  •   實現服務代理BpMediaPlayerService;

2 Client獲取Service服務

  Native Service以及framework Service都是加入到ServiceManger中,

不管native端還是Framework端得Service 其實都是要滿足上面遠程對象代理結構。

native端獲取service:

//獲取ServiceManager的代理對象
sp<IServiceManager> sm = defaultServiceManager(); //通過ServiceManager獲取media Service binder
binder = sm->getService(String16("media.player")); //將binder封裝 構造media Service代理對象 BpMediaPlayerService
sMediaPlayerService = interface_cast<IMediaPlayerService>(binder);

framework層的service,借助AIDL文件,實現跨進程的通信:

  所有framework端service想要作為公共的服務,被別的應用程序調用,都要實現AIDL文件,服務要繼承該AIDL文件內部類Stub。
其實AIDL文件是對Framework中service作為進程通信的框架的封裝,系統自動生成中間需要的代碼和步驟,統一結構:還是binder代理,服務代理。

下面看看PowerManagerService實現。
PowerManagerService服務:

\frameworks\base\services\java\com\android\server\PowerManagerService.java

public class PowerManagerService extends IPowerManager.Stub…… {   public void goToSleep(long time){     ……   } }; AIDL文件:\frameworks\base\core\java\android\os\IPowerManager.aidl interface IPowerManager {   void goToSleep(long time);   …… }

AIDL對應的Java文件:
  AIDL會自動生成一個對應的Java的interface文件,看看這個接口文件。
  AIDL自動生成對應java文件位置:\out\target\common\obj\JAVA_LIBRARIES\framework_intermediates\src\core\java\android\os

public interface IPowerManager extends android.os.IInterface { //IPowerManager 內部類 Stub
    public static abstract class Stub extends android.os.Binder implements android.os.IPowerManager { public static android.os.IPowerManager asInterface( android.os.IBinder obj) { //生成一個Proxy對象
            return new android.os.IPowerManager.Stub.Proxy(obj); } public android.os.IBinder asBinder() { return this; } @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) { switch (code) { case TRANSACTION_goToSleep: this.goToSleep(_arg0); return true; …… } } //Stub內部類Proxy 
        private static class Proxy implements android.os.IPowerManager { private android.os.IBinder mRemote; Proxy(android.os.IBinder remote) { mRemote = remote; } public void goToSleep(long time) { //將數據打包成Parcel
                android.os.Parcel _data = android.os.Parcel.obtain(); android.os.Parcel _reply = android.os.Parcel.obtain(); _data.writeInterfaceToken(DESCRIPTOR); _data.writeLong(time); //傳輸數據到binder 到相關的Service 進程 // IPCThreadState::transact方法中完成
                mRemote.transact(Stub.TRANSACTION_goToSleep, _data, _reply,0); _reply.readException(); } } } //goToSleep接口對應的ID
    static final int TRANSACTION_goToSleep = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2); //接口
    public void goToSleep(long time); }

看下其中類結構:

    


AIDL自動生成對應的java文件,將結構過程進行了統一,自動生成中間代碼。

Application獲取用Service:

IPowerManager m mPowerManagerService; //獲取service的bingder
IBinder binder = ServiceManager.getService("power"); //創建service代理對象
mPowerManagerService = IPowerManager.Stub.asInterface(binder); //調用接口
mPowerManagerService.goToSleep();

Native Service和 Framework Service結構方式基本一致的。

 

進程間通信Linux系統已經提供了很多方式,比如Socket,為什么Android非要另辟蹊徑,設計了Binder呢?

  可以閱讀一下:http://www.cnblogs.com/bastard/archive/2012/10/17/2728155.html


  Game Over !

參考文檔:
  http://www.cnblogs.com/innost/archive/2011/01/09/1931456.html
  http://blog.csdn.net/maxleng/article/details/5490770

注:

 

  “我們其實還一部分沒有研究,就是同一個進程之間的對象傳遞與遠程傳遞是區別的。同一個進程間專遞服務地和對象,

  就沒有代理BpBinder產生,而只是對象的直接應用了。應用程序並不知道數據是在同一進程間傳遞還是不同進程間傳遞,

  這個只有內核中的Binder知道,所以內核Binder驅動可以將Binder對象數據類型從BINDER_TYPE_BINDER修改為

  BINDER_TYPE_HANDLE或者BINDER_TYPE_WEAK_HANDLE作為引用傳遞。”  ——來自上述地址

  這個可以看到在SystemServer運行的Service之間使用時,直接轉化成了對應的對象,而不是通過代理。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM