生活随笔
收集整理的這篇文章主要介紹了
Android的IPC机制Binder
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
第一部分 Binder的組成?
1.1 驅動程序部分驅動程序的部分在以下的文件夾中:
Java代碼?
kernel/include/linux/binder.h ?? kernel/drivers/android/binder.c??
Java代碼??
kernel/include/linux/binder.h?? kernel/drivers/android/binder.c??
??? binder驅動程序是一個miscdevice,主設備號為10,此設備號使用動態獲得(MISC_DYNAMIC_MINOR),其設備的節點為:?
/dev/binder?
??? binder驅動程序會在proc文件系統中建立自己的信息,其文件夾為/proc/binder,其中包含如下內容:?
proc目錄:調用Binder各個進程的內容?
state文件:使用函數binder_read_proc_state?
stats文件:使用函數binder_read_proc_stats?
transactions文件:使用函數binder_read_proc_transactions?
transaction_log文件:使用函數binder_read_proc_transaction_log,其參數為binder_transaction_log (類型為struct binder_transaction_log)?
failed_transaction_log文件:使用函數binder_read_proc_transaction_log 其參數為?
binder_transaction_log_failed (類型為struct binder_transaction_log)?
??? 在binder文件被打開后,其私有數據(private_data)的類型:?
struct binder_proc?
??? 在這個數據結構中,主要包含了當前進程、進程ID、內存映射信息、Binder的統計信息和線程信息等。?
??? 在用戶空間對Binder驅動程序進行控制主要使用的接口是mmap、poll和ioctl,ioctl主要使用的ID為:
Java代碼?
#define?BINDER_WRITE_READ????????_IOWR('b',?1,?struct?binder_write_read) ?? #define?BINDER_SET_IDLE_TIMEOUT??_IOW('b',?3,?int64_t) ?? #define?BINDER_SET_MAX_THREADS???_IOW('b',?5,?size_t) ?? #define?BINDER_SET_IDLE_PRIORITY?_IOW('b',?6,?int) ?? #define?BINDER_SET_CONTEXT_MGR???_IOW('b',?7,?int) ?? #define?BINDER_THREAD_EXIT???????_IOW('b',?8,?int) ?? #define?BINDER_VERSION???????????_IOWR('b',?9,?struct?binder_version)??
Java代碼??
#define?BINDER_WRITE_READ????????_IOWR('b',?1,?struct?binder_write_read)?? #define?BINDER_SET_IDLE_TIMEOUT??_IOW('b',?3,?int64_t)?? #define?BINDER_SET_MAX_THREADS???_IOW('b',?5,?size_t)?? #define?BINDER_SET_IDLE_PRIORITY?_IOW('b',?6,?int)?? #define?BINDER_SET_CONTEXT_MGR???_IOW('b',?7,?int)?? #define?BINDER_THREAD_EXIT???????_IOW('b',?8,?int)?? #define?BINDER_VERSION???????????_IOWR('b',?9,?struct?binder_version)??
??? BR_XXX等宏為BinderDriverReturnProtocol,表示Binder驅動返回協議。?
??? BC_XXX等宏為BinderDriverCommandProtocol,表示Binder驅動命令協議。?
??? binder_thread是Binder驅動程序中使用的另外一個重要的數據結構,數據結構的定義如下所示:
Java代碼?
struct?binder_thread?{ ?? ??????struct?binder_proc?*proc; ?? ?????struct?rb_node?rb_node; ?? ?????int?pid; ?? ?????int?looper; ?? ?????struct?binder_transaction?*transaction_stack; ?? ?????struct?list_head?todo; ?? ?????uint32_t?return_error; ?? ?????uint32_t?return_error2; ?? ?????wait_queue_head_t?wait; ?? ?????struct?binder_stats?stats; ?? };??
Java代碼??
struct?binder_thread?{?? ??????struct?binder_proc?*proc;?? ?????struct?rb_node?rb_node;?? ?????int?pid;?? ?????int?looper;?? ?????struct?binder_transaction?*transaction_stack;?? ?????struct?list_head?todo;?? ?????uint32_t?return_error;?? ?????uint32_t?return_error2;?? ?????wait_queue_head_t?wait;?? ?????struct?binder_stats?stats;?? };??
??? binder_thread 的各個成員信息是從rb_node中得出。?
??? BINDER_WRITE_READ是最重要的ioctl,它使用一個數據結構binder_write_read定義讀寫的數據。
Java代碼?
struct?binder_write_read?{ ?? ?????signed?long?write_size; ?? ?????signed?long?write_consumed; ?? ?????unsigned?long?write_buffer; ?? ?????signed?long?read_size; ?? ?????signed?long?read_consumed; ?? ?????unsigned?long?read_buffer; ?? };??
Java代碼??
struct?binder_write_read?{?? ?????signed?long?write_size;?? ?????signed?long?write_consumed;?? ?????unsigned?long?write_buffer;?? ?????signed?long?read_size;?? ?????signed?long?read_consumed;?? ?????unsigned?long?read_buffer;?? };??
1.2 servicemanager部分??????? servicemanager是一個守護進程,用于這個進程的和/dev/binder通訊,從而達到管理系統中各個服務的作用。?
??????? 可執行程序的路徑:?
??????? /system/bin/servicemanager????????
開源版本文件的路徑:
Java代碼?
frameworks/base/cmds/servicemanager/binder.h ?? frameworks/base/cmds/servicemanager/binder.c ?? frameworks/base/cmds/servicemanager/service_manager.c??
Java代碼??
frameworks/base/cmds/servicemanager/binder.h?? frameworks/base/cmds/servicemanager/binder.c?? frameworks/base/cmds/servicemanager/service_manager.c??
?????? 程序執行的流程:?
open():打開binder驅動?
mmap():映射一個128*1024字節的內存?
ioctl(BINDER_SET_CONTEXT_MGR):設置上下文為mgr?
?????? 進入主循環binder_loop()?
???????????? ioctl(BINDER_WRITE_READ),讀取?
?????????????????????? binder_parse()進入binder處理過程循環處理?
???????? binder_parse()的處理,調用返回值:?
??????? 當處理BR_TRANSACTION的時候,調用svcmgr_handler()處理增加服務、檢查服務等工作。各種服務存放在一個鏈表(svclist)中。其中調用binder_等開頭的函數,又會調用ioctl的各種命令。?
??????? 處理BR_REPLY的時候,填充binder_io類型的數據結?
1.3 binder的庫的部分?
??? binder相關的文件作為Android的uitls庫的一部分,這個庫編譯后的名稱為libutils.so,是Android系統中的一個公共庫。?
??? 主要文件的路徑如下所示:
Java代碼?
frameworks/base/include/utils/* ?? frameworks/base/libs/utils/*??
Java代碼??
frameworks/base/include/utils/*?? frameworks/base/libs/utils/*??
???
??? 主要的類為:?
RefBase.h :?
??? 引用計數,定義類RefBase。?
Parcel.h :?
??? 為在IPC中傳輸的數據定義容器,定義類Parcel?
IBinder.h:?
??? Binder對象的抽象接口, 定義類IBinder?
Binder.h:?
??? Binder對象的基本功能, 定義類Binder和BpRefBase?
BpBinder.h:?
BpBinder的功能,定義類BpBinder?
IInterface.h:?
為抽象經過Binder的接口定義通用類,?
??? 定義類IInterface,類模板BnInterface,類模板BpInterface?
ProcessState.h?
??? 表示進程狀態的類,定義類ProcessState?
IPCThreadState.h?
??? 表示IPC線程的狀態,定義類IPCThreadState?
各個類之間的關系如下所示:?
??? 在IInterface.h中定義的BnInterface和BpInterface是兩個重要的模版,這是為各種程序中使用的。?
BnInterface模版的定義如下所示:
Java代碼?
template ?? class?BnInterface?:?public?INTERFACE,?public?BBinder ?? { ?? public: ?? ????virtual?sp??queryLocalInterface(const?String16&?_descriptor); ?? ????virtual?String16????????getInterfaceDescriptor()?const; ?? protected: ?? ????virtual?IBinder*????????onAsBinder(); ?? }; ?? ?????BnInterface模版的定義如下所示: ?? template ?? class?BpInterface?:?public?INTERFACE,?public?BpRefBase ?? { ?? public: ?? ????????????????????????????BpInterface(const?sp&?remote); ?? protected: ?? ????virtual?IBinder*????onAsBinder(); ?? };??
Java代碼??
template?? class?BnInterface?:?public?INTERFACE,?public?BBinder?? {?? public:?? ????virtual?sp??queryLocalInterface(const?String16&?_descriptor);?? ????virtual?String16????????getInterfaceDescriptor()?const;?? protected:?? ????virtual?IBinder*????????onAsBinder();?? };?? ?????BnInterface模版的定義如下所示:?? template?? class?BpInterface?:?public?INTERFACE,?public?BpRefBase?? {?? public:?? ????????????????????????????BpInterface(const?sp&?remote);?? protected:?? ????virtual?IBinder*????onAsBinder();?? };??
???????? 這兩個模版在使用的時候,起到得作用實際上都是雙繼承:使用者定義一個接口INTERFACE,然后使用BnInterface和BpInterface兩個模版結合自己的接口,構建自己的BnXXX和BpXXX兩個類。?
???????? DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE兩個宏用于幫助BpXXX類的實現:
Java代碼?
#define?DECLARE_META_INTERFACE(INTERFACE)???????????????????????????????\ ?? ????static?const?String16?descriptor;???????????????????????????????????\ ?? ????static?sp?asInterface(const?sp&?obj);????????\ ?? ????virtual?String16?getInterfaceDescriptor()?const;????????????????????\ ?? #define?IMPLEMENT_META_INTERFACE(INTERFACE,?NAME)???????????????????????\ ?? ????const?String16?I##INTERFACE::descriptor(NAME);??????????????????????\ ?? ????String16?I##INTERFACE::getInterfaceDescriptor()?const?{?????????????\ ?? ????????return?I##INTERFACE::descriptor;????????????????????????????????\ ?? ????}???????????????????????????????????????????????????????????????????\ ?? ????sp?I##INTERFACE::asInterface(const?sp&?obj)??\ ?? ????{???????????????????????????????????????????????????????????????????\ ?? ????????sp?intr;??????????????????????????????????????????\ ?? ????????if?(obj?!=?NULL)?{??????????????????????????????????????????????\ ?? ????????????intr?=?static_cast(??????????????????????????\ ?? ????????????????obj->queryLocalInterface(???????????????????????????????\ ?? ????????????????????????I##INTERFACE::descriptor).get());???????????????\ ?? ????????????if?(intr?==?NULL)?{?????????????????????????????????????????\ ?? ????????????????intr?=?new?Bp##INTERFACE(obj);??????????????????????????\ ?? ????????????}???????????????????????????????????????????????????????????\ ?? ????????}???????????????????????????????????????????????????????????????\ ?? ????????return?intr;????????????????????????????????????????????????????\ ?? ????}??
Java代碼??
#define?DECLARE_META_INTERFACE(INTERFACE)???????????????????????????????\?? ????static?const?String16?descriptor;???????????????????????????????????\?? ????static?sp?asInterface(const?sp&?obj);????????\?? ????virtual?String16?getInterfaceDescriptor()?const;????????????????????\?? #define?IMPLEMENT_META_INTERFACE(INTERFACE,?NAME)???????????????????????\?? ????const?String16?I##INTERFACE::descriptor(NAME);??????????????????????\?? ????String16?I##INTERFACE::getInterfaceDescriptor()?const?{?????????????\?? ????????return?I##INTERFACE::descriptor;????????????????????????????????\?? ????}???????????????????????????????????????????????????????????????????\?? ????sp?I##INTERFACE::asInterface(const?sp&?obj)??\?? ????{???????????????????????????????????????????????????????????????????\?? ????????sp?intr;??????????????????????????????????????????\?? ????????if?(obj?!=?NULL)?{??????????????????????????????????????????????\?? ????????????intr?=?static_cast(??????????????????????????\?? ????????????????obj->queryLocalInterface(???????????????????????????????\?? ????????????????????????I##INTERFACE::descriptor).get());???????????????\?? ????????????if?(intr?==?NULL)?{?????????????????????????????????????????\?? ????????????????intr?=?new?Bp##INTERFACE(obj);??????????????????????????\?? ????????????}???????????????????????????????????????????????????????????\?? ????????}???????????????????????????????????????????????????????????????\?? ????????return?intr;????????????????????????????????????????????????????\?? ????}??
??
?? 在定義自己的類的時候,只需要使用DECLARE_META_INTERFACE和IMPLEMENT_META_INTERFACE兩個接口,并?
結合類的名稱,就可以實現BpInterface中的asInterface()和getInterfaceDescriptor()兩個函數。?
第二部分 Binder的運作?
2.1 Binder的工作機制?
????? Service Manager是一個守護進程,它負責啟動各個進程之間的服務,對于相關的兩個需要通訊的進程,它們通過調用libutil.so庫實現通訊,而真正通訊的機制,是內核空間中的一塊共享內存。?
??????
2.2 從應 用程序的角度看Binder?
從應用程序的角度看Binder一共有三個方面:?
Native 本地:例如BnABC,這是一個需要被繼承和實現的類。?
Proxy 代理:例如BpABC,這是一個在接口框架中被實現,但是在接口中沒有體現的類。?
客戶端:例如客戶端得到一個接口ABC,在調用的時候實際上被調用的是BpABC?
本地功能(Bn)部分做的:?
??? 實現BnABC:: BnTransact()?
??? 注冊服務:IServiceManager::AddService?
代理部分(Bp)做的:?
??? 實現幾個功能函數,調用BpABC::remote()->transact()?
客戶端做的:?
??? 獲得ABC接口,然后調用接口(實際上調用了BpABC,繼而通過IPC調用了BnABC,然后調用了具體的功能)?
?????? 在程序的實現過程中BnABC和BpABC是雙繼承了接口ABC。一般來說BpABC是一個實現類,這個實現類不需要在接口中體現,它實際上負責的只是通訊功能,不執行具體的功能;BnABC則是一個接口類,需要一個真正工作的類來繼承、實現它,這個類才是真正執行具體功能的類。?
?????? 在客戶端中,從ISeriviceManager中獲得一個ABC的接口,客戶端調用這個接口,實際上是在調用BpABC,而BpABC又通過Binder的IPC機制和BnABC通訊,BnABC的實現類在后面執行。?
事實上,?
服務器?
的具體實現和客戶端是兩個不同的進程,如果不考慮進程間通訊的過程,從調用者的角度,似乎客戶端在直接調用另外一個進程間的函數——當然這個函數必須是接口ABC中定義的。?
2.3 ISericeManager的作用?
??? ISericeManager涉及的兩個文件是ISericeManager.h和ISericeManager.cpp。這兩個文件基本上是?
ISericeManager。ISericeManager是系統最先被啟動的服務。非常值得注意的是:ISericeManager本地功能并沒有使?
現,它實際上由ServiceManager守護進程執行,而用戶程序通過調用BpServiceManager來獲得其他的服務。?
????? 在ISericeManager.h中定義了一個接口,用于得到默認的ISericeManager:?
??????? sp defaultServiceManager();?
???? 這時得到的ISericeManager實際上是一個全局的ISericeManager。?
第三部分 程序中Binder的具體實現?
3.1 一個利用接口的具體實現?
??? PermissionController也是libutils中定義的一個有關權限控制的接口,它一共包含兩個文件:IPermissionController.h和IPermissionController.cpp這個結構在所有類的實現中都是類似的。?
???? 頭文件IPermissionController.h的主要內容是定義IPermissionController接口和類BnPermissionController:
Java代碼?
class?IPermissionController?:?public?IInterface ?? { ?? public: ?? ????DECLARE_META_INTERFACE(PermissionController); ?? ????virtual?bool???checkPermission(const?String16&?permission,int32_t?pid,?int32_t?uid)?=?0; ?? ????enum?{ ?? ????????CHECK_PERMISSION_TRANSACTION?=?IBinder::FIRST_CALL_TRANSACTION ?? ????}; ?? }; ?? class?BnPermissionController?:?public?BnInterface ?? { ?? public: ?? ????virtual?status_t????onTransact(?uint32_t?code, ?? ????????????????????????????????????const?Parcel&?data, ?? ????????????????????????????????????Parcel*?reply, ?? ????????????????????????????????????uint32_t?flags?=?0); ?? };??
Java代碼??
class?IPermissionController?:?public?IInterface?? {?? public:?? ????DECLARE_META_INTERFACE(PermissionController);?? ????virtual?bool???checkPermission(const?String16&?permission,int32_t?pid,?int32_t?uid)?=?0;?? ????enum?{?? ????????CHECK_PERMISSION_TRANSACTION?=?IBinder::FIRST_CALL_TRANSACTION?? ????};?? };?? class?BnPermissionController?:?public?BnInterface?? {?? public:?? ????virtual?status_t????onTransact(?uint32_t?code,?? ????????????????????????????????????const?Parcel&?data,?? ????????????????????????????????????Parcel*?reply,?? ????????????????????????????????????uint32_t?flags?=?0);?? };??
??? IPermissionController是一個接口類,只有checkPermission()一個純虛函數。?
BnPermissionController繼承了以BnPermissionController實例化模版類BnInterface。因?
此,BnPermissionController,事實上BnPermissionController雙繼承了BBinder和?
IPermissionController。?
??? 實現文件IPermissionController.cpp中,首先實現了一個BpPermissionController。
Java代碼?
class?BpPermissionController?:?public?BpInterface ?? { ?? public: ?? ????BpPermissionController(const?sp&?impl) ?? ????????:?BpInterface(impl) ?? ????{ ?? ????} ?? ????virtual?bool?checkPermission(const?String16&?permission,?int32_t?pid,?int32_t?uid) ?? ????{ ?? ????????Parcel?data,?reply; ?? ????????data.writeInterfaceToken(IPermissionController:: ?? ???????????????????????????????????????getInterfaceDescriptor()); ?? ????????data.writeString16(permission); ?? ????????data.writeInt32(pid); ?? ????????data.writeInt32(uid); ?? ????????remote()->transact(CHECK_PERMISSION_TRANSACTION,?data,?&reply); ?? ????????if?(reply.readInt32()?!=?0)?return?0; ?? ????????return?reply.readInt32()?!=?0; ?? ????} ?? };??
Java代碼??
class?BpPermissionController?:?public?BpInterface?? {?? public:?? ????BpPermissionController(const?sp&?impl)?? ????????:?BpInterface(impl)?? ????{?? ????}?? ????virtual?bool?checkPermission(const?String16&?permission,?int32_t?pid,?int32_t?uid)?? ????{?? ????????Parcel?data,?reply;?? ????????data.writeInterfaceToken(IPermissionController::?? ???????????????????????????????????????getInterfaceDescriptor());?? ????????data.writeString16(permission);?? ????????data.writeInt32(pid);?? ????????data.writeInt32(uid);?? ????????remote()->transact(CHECK_PERMISSION_TRANSACTION,?data,?&reply);?? ????????if?(reply.readInt32()?!=?0)?return?0;?? ????????return?reply.readInt32()?!=?0;?? ????}?? };??
IMPLEMENT_META_INTERFACE(PermissionController, "android.os.IPermissionController");?
BpPermissionController繼承了BpInterface,它本身是一個?
已經實現的類,而且并沒有在接口中體現。這個類按照格式寫就可以,在實現checkPermission()函數的過程中,使用Parcel作為傳輸數據?
的容器,傳輸中時候transact()函數,其參數需要包含枚舉值CHECK_PERMISSION_TRANSACTION。?
IMPLEMENT_META_INTERFACE用于扶助生成。?
??? BnPermissionController中實現的onTransact()函數如下所示:
Java代碼?
status_t?BnPermissionController::?BnTransact( ?? ????uint32_t?code,?const?Parcel&?data,?Parcel*?reply,?uint32_t?flags) ?? { ?? ????switch(code)?{ ?? ????????case?CHECK_PERMISSION_TRANSACTION:?{ ?? ????????????CHECK_INTERFACE(IPermissionController,?data,?reply); ?? ????????????String16?permission?=?data.readString16(); ?? ????????????int32_t?pid?=?data.readInt32(); ?? ????????????int32_t?uid?=?data.readInt32(); ?? ????????????bool?res?=?checkPermission(permission,?pid,?uid); ?? ????????????reply->writeInt32(0); ?? ????????????reply->writeInt32(res???1?:?0); ?? ????????????return?NO_ERROR; ?? ????????}?break; ?? ????????default: ?? ????????????return?BBinder::?BnTransact(code,?data,?reply,?flags); ?? ????} ?? }??
Java代碼??
status_t?BnPermissionController::?BnTransact(?? ????uint32_t?code,?const?Parcel&?data,?Parcel*?reply,?uint32_t?flags)?? {?? ????switch(code)?{?? ????????case?CHECK_PERMISSION_TRANSACTION:?{?? ????????????CHECK_INTERFACE(IPermissionController,?data,?reply);?? ????????????String16?permission?=?data.readString16();?? ????????????int32_t?pid?=?data.readInt32();?? ????????????int32_t?uid?=?data.readInt32();?? ????????????bool?res?=?checkPermission(permission,?pid,?uid);?? ????????????reply->writeInt32(0);?? ????????????reply->writeInt32(res???1?:?0);?? ????????????return?NO_ERROR;?? ????????}?break;?? ????????default:?? ????????????return?BBinder::?BnTransact(code,?data,?reply,?flags);?? ????}?? }??
???? 在onTransact()函數中根據枚舉值判斷數據使用的方式。注意,由于BnPermissionController也是繼承了類?
IPermissionController,但是純虛函數checkPermission()依然沒有實現。因此這個?
BnPermissionController類并不能實例化,它其實也還是一個接口,需要一個實現類來繼承它,那才是實現具體功能的類。?
3.2 BnABC的實現?
??? 本地服務啟動后將形成一個守護進程,具體的本地服務是由一個實現類繼承BnABC來實現的,這個服務的名稱通常叫做ABC。?
??? 在其中,通常包含了一個instantiate()函數,這個函數一般按照如下的方式實現:?
void ABC::instantiate() {?
??? defaultServiceManager()->addService(?
??????????? String16("XXX.ABC"), new ABC ());?
}?
??? 按照這種方式,通過調用defaultServiceManager()函數,將增加一個名為"XXX.ABC"的服務。?
??? 在這個defaultServiceManager()函數中調用了:?
ProcessState::self()->getContextObject(NULL));?
??? IPCThreadState* ipc = IPCThreadState::self();?
?? IPCThreadState::talkWithDriver()?
在ProcessState 類建立的過程中調用open_driver()打開?
驅動?
程序,在talkWithDriver()的執行過程中。?
3.3 BpABC調用的實現?
??? BpABC調用的過程主要通過mRemote()->transact() 來傳輸數據,mRemote()是BpRefBase的成員,它是一個IBinder。這個調用過程如下所示:?
???
Java代碼?
mRemote()->transact() ?? ????Process::self() ?? ????IPCThreadState::self()->transact() ?? ????writeTransactionData() ?? ????waitForResponse() ?? ????talkWithDriver() ?? ????ioctl(fd,?BINDER_WRITE_READ,?&bwr)??
Java代碼??
mRemote()->transact()?? ????Process::self()?? ????IPCThreadState::self()->transact()?? ????writeTransactionData()?? ????waitForResponse()?? ????talkWithDriver()?? ????ioctl(fd,?BINDER_WRITE_READ,?&bwr)??
??? 在IPCThreadState::executeCommand()函數中,實現傳輸操作。
(hanchao3c?Android開發者論壇原創)
總結
以上是生活随笔為你收集整理的Android的IPC机制Binder的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。