Binder是Android中使用的進程間通訊機制(IPC)。在Android系統中,應用程序是由Activity、Service、Broadcast Receiver和Content Provider四種類型的組件構成的,它們有可能運行在同一進程中,也有可能運行在不一樣的進程中。此外,各類系統組件也運行在獨立的進程中。這些運行在不一樣進程中的應用程序組件和系統組件之間的通訊機制就是Binder。
Android雖然構建在Linux上面,可是在IPC機制方面,沒有利用Linux提供IPC機制,而是使用了一套輕量級的IPC機制—Binder機制。Binder是基於OpenBinder來實現的。OpenBinder最早是由Be Inc.開發的,接着Palm Inc.也跟着使用。Binder是一種進程間通訊機制,它是一種相似於COM和CORBA分佈式組件架構,通俗一點,實際上是提供遠程過程調用(RPC)功能。android
Binder具備如下特色編程
Binder應用模型
一個IPC通信咱們能夠簡單理解成Client-Server模式,Client請求Service,Server接收到Client請求後處理相應,或可能帶回結果返回給Client。
服務器
Binder機制在Android系統的進程間通信模型總結以下:網絡
Binder機制的組成多線程
下面以一個簡單實例來分析Binder傳輸。該測試程序由client端調用add()函數,在server端完成加法操做,並返回結果。測試程序的目錄結構以下,
架構
類圖以下所示。左側爲server端,右側爲client端。
併發
從Client端的代碼看起。Client若是想和Server進行通訊,必須先得到Server的遠程接口,這個過程經過Service Manager來實現。Service Manager用來管理Server而且向Client提供查詢Server遠程接口的功能。分佈式
1.---> BinderClientRun.cpp 2. 3.int main(int argc, char** argv) 4.{ 5. int sum = 0; 6. sp<IBinderServiceTest> mBinderServiceTest; 7. 8. if (mBinderServiceTest.get() == 0) { 9. // 經過defaultServiceManager函數來得到Service Manager的遠程接口 10. sp<IServiceManager> sm = defaultServiceManager(); 11. sp<IBinder> binder; 12. 13. // 在循環中使用sm->getService不斷嘗試得到名稱爲「my.binder.test」的Service,返回binder 14. do { 15. binder = sm->getService(String16("my.binder.test")); 16. if (binder != 0) 17. break; 18. ALOGI("getService fail"); 19. usleep(500000); // 0.5 s 20. } while (true); 21. 22. // 獲得Service的binder後,經過interface_cast,將這個binder轉化成BpBinderServiceTest 23. mBinderServiceTest = interface_cast<IBinderServiceTest> (binder); 24. ALOGE_IF(mBinderServiceTest == 0, "no IBinderServiceTest!?"); 25. } 26. 27. // BpBinderServiceTest,就能夠調用遠程server的接口了 28. sum = mBinderServiceTest->add(3, 4); 29. ALOGI("sum = %d", sum); 30. return 0; 31.}
代碼中的interface_cast是如何將binder轉化爲BpBinderServiceTest的呢?Android有意隱藏了這一轉換,讓應用很輕鬆的完成這一轉換。看一下interface_cast的定義ide
1.---> IInterface.h 2. 3.template<typename INTERFACE> 4.inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj) 5.{ 6. return INTERFACE::asInterface(obj); 7.}
interface_cast是一個模板,它返回的是 IBinderServiceTest::asInterface。但在咱們的源碼中並無直接實現 asInterface,那它是在哪裏實現的呢?讓咱們先看一下兩個宏定義函數
1.---> IInterface.h 2. 3.#define DECLARE_META_INTERFACE(INTERFACE) \ 4. static const android::String16 descriptor; \ 5. static android::sp<I##INTERFACE> asInterface( \ 6. const android::sp<android::IBinder>& obj); \ 7. virtual const android::String16& getInterfaceDescriptor() const; \ 8. I##INTERFACE(); \ 9. virtual ~I##INTERFACE(); \ 10. 11. 12.#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \ 13. const android::String16 I##INTERFACE::descriptor(NAME); \ 14. const android::String16& \ 15. I##INTERFACE::getInterfaceDescriptor() const { \ 16. return I##INTERFACE::descriptor; \ 17. } \ 18. android::sp<I##INTERFACE> I##INTERFACE::asInterface( \ 19. const android::sp<android::IBinder>& obj) \ 20. { \ 21. android::sp<I##INTERFACE> intr; \ 22. if (obj != NULL) { \ 23. intr = static_cast<I##INTERFACE*>( \ 24. obj->queryLocalInterface( \ 25. I##INTERFACE::descriptor).get()); \ 26. if (intr == NULL) { \ 27. intr = new Bp##INTERFACE(obj); \ 28. } \ 29. } \ 30. return intr; \ 31. } \ 32. I##INTERFACE::I##INTERFACE() { } \ 33. I##INTERFACE::~I##INTERFACE() { }
這兩個宏會在程序中被使用
1.---> IBinderServiceTest.h 2. 3.class IBinderServiceTest: public IInterface { 4.public: 5. DECLARE_META_INTERFACE(BinderServiceTest); 6. 7. virtual int add(int a, int b) = 0; 8.}; 9. 10. 11.---> IBinderServiceTest.cpp 12. 13.IMPLEMENT_META_INTERFACE(BinderServiceTest, "android.test.IBinderServiceTest");
將這兩個宏展開會等到
1.---> IBinderServiceTest.h 2. 3.class IBinderServiceTest: public IInterface { 4.public: 5. static const android::String16 descriptor; 6. static android::sp<IBinderServiceTest > asInterface 7. (const android::sp<android::IBinder>& obj); 8. virtual const android::String16& getInterfaceDescriptor() const; 9. IBinderServiceTest (); 10. virtual ~IBinderServiceTest (); 11. virtual int add(int a, int b) = 0; 12.};
1.---> IBinderServiceTest.cpp 2. 3. const android::String16 IBinderServiceTest ::descriptor("android.test.IBinderServiceTest"); 4. const android::String16& IBinderServiceTest ::getInterfaceDescriptor() const { 5. return IBinderServiceTest ::descriptor; 6. } 7. android::sp<IBinderServiceTest > IBinderServiceTest ::asInterface 8. (const android::sp<android::IBinder>& obj) 9. { 10. android::sp<IBinderServiceTest > intr; 11. if (obj != NULL) { 12. intr = static_cast<IBinderServiceTest *> 13. (obj->queryLocalInterface(IBinderServiceTest ::descriptor).get()); 14. if (intr == NULL) { 15. intr = new BpBinderServiceTest (obj); 16. } 17. } 18. return intr; 19. } 20. IBinderServiceTest ::IBinderServiceTest () { } 21. IBinderServiceTest ::~IBinderServiceTest () { }
展開的宏裏,咱們找到了asInterface,這裏new了一個 BpBinderServiceTest,而後將其返回。Client端獲得Server端的代理BpBinderServiceTest後,就能夠像本地調用同樣來使用Server端的接口。示例程序中調用了add()函數,看一下它早Proxy中的實現。
1.---> IBinderServiceTest.cpp 2. 3.class BpBinderServiceTest: public BpInterface<IBinderServiceTest> 4.{ 5.public: 6. BpBinderServiceTest(const sp<IBinder>& impl) : 7. BpInterface<IBinderServiceTest> (impl) { 8. } 9. 10. int add(int a, int b) { 11. // Parcel類用來於序列化進程間通訊數據。 12. Parcel data, reply; 13. ALOGI("BpBinderServiceTest add, a = %d, b = %d", a, b); 14. 15. // 寫入Binder傳輸數據的頭,這裏寫入Service描述符「android.test.IBinderServiceTest」。 16. data.writeInterfaceToken(IBinderServiceTest::getInterfaceDescriptor()); 17. // 以後向Binder中寫入要發送給Server的數據。 18. data.writeInt32(a); 19. data.writeInt32(b); 20. // 開始進行遠端的傳輸調用。 21. remote()->transact(TEST_ADD, data, &reply); 22. // 讀取Server返回的數據。 23. int sum = reply.readInt32(); 24. 25. ALOGI("BpBinderServiceTest sum = %d", sum); 26. return sum; 27. } 28.};
代碼中,remote()來自於BpRefBase類,它返回一個BpBinder指針,所以這將調用BpBinder::transact。TEST_ADD是Binder執行的命令編碼,Server會根據這個值來執行相應的命令。實際的Binder傳輸是在IPCThreadState中完成的,傳輸時同步的,調用返回表示Server端已經執行結束。這裏不作詳解。
Client端發送命令TEST_ADD,看看Server端是如何執行這個命令的。
1.---> IBinderServiceTest.cpp 2. 3.status_t BnBinderServiceTest::onTransact(uint32_t code, const Parcel& data, 4. Parcel* reply, uint32_t flags) { 5. switch (code) { 6. // 接收到Client端的命令TEST_ADD。 7. case TEST_ADD: { 8. // 檢查數據頭是否爲Service描述符。 9. CHECK_INTERFACE(IBinderServiceTest, data, reply); 10. 11. // 讀取輸入的數據。 12. int a = data.readInt32(); 13. int b = data.readInt32(); 14. ALOGI("BnBinderServiceTest add, a = %d b = %d", a, b); 15. 16. int sum = 0; 17. // 調用Server對應的函數 18. sum = add(a, b); 19. ALOGI("BnBinderServiceTest sum = %d", sum); 20. // 寫入返回數據到Binder。 21. reply->writeInt32(sum); 22. return sum; 23. } 24. default: 25. return BBinder::onTransact(code, data, reply, flags); 26. } 27.}
Server端的源頭也是在IPCThreadState中。IPCThreadState藉助ProcessState類來與Binder驅動程序交互,接收Client處的請求。以後調用BBinder類的transact函數,並傳入相關參數。BBinder類的transact函數最終調用BnBinderServiceTest類的onTransact函數。
下面從Server端啓動開始分析。
1.---> BinderServerRun.cpp 2. 3.int main(int argc, char** argv) 4. { 5. // 建立一個ProcessState實例。 6. sp<ProcessState> proc(ProcessState::self()); 7. // 獲得Service Manager的遠程接口。 8. sp<IServiceManager> sm = defaultServiceManager(); 9. 10. // 增長Service "my.binder.test"到Service Manager中。 11. BinderServiceTest::instantiate(); 12. ProcessState::self()->startThreadPool(); 13. IPCThreadState::self()->joinThreadPool(); 14. return 0; 15.} 16. 17. 18.---> BinderTestServer.cpp 19. 20.void BinderServiceTest::instantiate() { 21. ALOGI("Enter instantiate"); 22. 23. status_t st = defaultServiceManager()->addService( 24. String16("my.binder.test"), new BinderServiceTest()); 25. ALOGD("addService ret=%d", st); 26.} 27. 28.BinderServiceTest::BinderServiceTest() { 29. ALOGD("Constructor"); 30.} 31. 32.BinderServiceTest::~BinderServiceTest() { 33. ALOGD("Destructor"); 34.} 35. 36.int BinderServiceTest::add(int a, int b) { 37. ALOGI("add a = %d, b = %d.", a, b); 38. return a+b; 39.}
Server端首先要經過ProcessState::self()調用建立一個ProcessState實例。ProcessState::self()是ProcessState類的一個靜態成員變量,這個函數返回一個全局惟一的ProcessState實例gProcess。代碼以下
1.---> ProcessState.cpp 2. 3.sp<ProcessState> ProcessState::self() 4.{ 5. Mutex::Autolock _l(gProcessMutex); 6. if (gProcess != NULL) { 7. return gProcess; 8. } 9. gProcess = new ProcessState; 10. return gProcess; 11.}
ProcessState實例化的過程當中主要完成兩個工做。一是會經過open_driver函數打開Binder設備文件/dev/binder,並將打開設備文件描述符保存在成員變量mDriverFD中;二是經過mmap來把設備文件/dev/binder映射到內存中。這裏不作詳解。
接下來分析startThreadPool()和joinThreadPool()到底作了什麼。startThreadPool() 的實現以下面的代碼所示:
1.---> ProcessState.cpp 2. 3.void ProcessState::startThreadPool() 4.{ 5. AutoMutex _l(mLock); 6. if (!mThreadPoolStarted) { 7. mThreadPoolStarted = true; 8. spawnPooledThread(true); 9. } 10.} 11....... 12.void ProcessState::spawnPooledThread(bool isMain) 13.{ 14. if (mThreadPoolStarted) { 15. String8 name = makeBinderThreadName(); 16. ALOGV("Spawning new pooled thread, name=%s\n", name.string()); 17. sp<Thread> t = new PoolThread(isMain); 18. t->run(name.string()); 19. } 20.}
PoolThread 是在 IPCThreadState 中定義的一個 Thread 子類,它的實現以下所示:
1.---> ProcessState.cpp 2. 3.class PoolThread : public Thread 4.{ 5.public: 6. PoolThread(bool isMain) 7. : mIsMain(isMain) 8. { 9. } 10. 11.protected: 12. virtual bool threadLoop() 13. { 14. IPCThreadState::self()->joinThreadPool(mIsMain); 15. return false; 16. } 17. 18. const bool mIsMain; 19.};
PoolThread繼承Thread類,其run函數調用Thread::run()建立一個線程,最終調用子類的threadLoop函數。threadLoop()也是調用joinThreadPool()完成工做。joinThreadPool()的代碼以下。
1.---> IPCThreadState.cpp 2. 3.status_t IPCThreadState::getAndExecuteCommand() 4.{ 5. status_t result; 6. int32_t cmd; 7. 8. result = talkWithDriver(); 9. if (result >= NO_ERROR) { 10. size_t IN = mIn.dataAvail(); 11. if (IN < sizeof(int32_t)) return result; 12. cmd = mIn.readInt32(); 13. IF_LOG_COMMANDS() { 14. alog << "Processing top-level Command: " 15. << getReturnString(cmd) << endl; 16. } 17. 18. result = executeCommand(cmd); 19. 20. // After executing the command, ensure that the thread is returned to the 21. // foreground cgroup before rejoining the pool. The driver takes care of 22. // restoring the priority, but doesn't do anything with cgroups so we 23. // need to take care of that here in userspace. Note that we do make 24. // sure to go in the foreground after executing a transaction, but 25. // there are other callbacks into user code that could have changed 26. // our group so we want to make absolutely sure it is put back. 27. set_sched_policy(mMyThreadId, SP_FOREGROUND); 28. } 29. 30. return result; 31.} 32....... 33.void IPCThreadState::joinThreadPool(bool isMain) 34.{ 35. LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid()); 36. 37. mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER); 38. 39. // This thread may have been spawned by a thread that was in the background 40. // scheduling group, so first we will make sure it is in the foreground 41. // one to avoid performing an initial transaction in the background. 42. set_sched_policy(mMyThreadId, SP_FOREGROUND); 43. 44. status_t result; 45. do { 46. processPendingDerefs(); 47. // now get the next command to be processed, waiting if necessary 48. result = getAndExecuteCommand(); 49. 50. if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) { 51. ALOGE("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting", 52. mProcess->mDriverFD, result); 53. abort(); 54. } 55. 56. // Let this thread exit the thread pool if it is no longer 57. // needed and it is not the main process thread. 58. if(result == TIMED_OUT && !isMain) { 59. break; 60. } 61. } while (result != -ECONNREFUSED && result != -EBADF); 62. 63. LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%p\n", 64. (void*)pthread_self(), getpid(), (void*)result); 65. 66. mOut.writeInt32(BC_EXIT_LOOPER); 67. talkWithDriver(false); 68.}
這個函數最終是在一個無窮循環中,經過調用talkWithDriver函數來和Binder驅動程序進行交互,實際上就是調用talkWithDriver來等待Client的請求,而後再調用executeCommand來處理請求,而在executeCommand函數中,最終會調用BBinder::transact來真正處理Client的請求。而BBinder::transact最終會調用onTransact函數來處理,也就實際調用了示例中的BnBinderServiceTest::onTransact。