原文地址:http://tech.it168.com/a2009/0331/270/000000270388.shtml
【內容導航】
- 第一部分 Binder的組成
- 第二部分 Binder的運作
- 第三部分 程序中Binder的具體實現
1Binder的組成
1.1 驅動程序部分
驅動程序的部分在以下的文件夾中:
kernel/include/linux/binder.h
kernel/drivers/misc/binder.c
binder驅動程序是一個miscdevice,主設備號爲10,此設備號使用動態獲得(MISC_DYNAMIC_MINOR),其設備的節點爲:
/dev/binder
binder驅動程序會在proc文件系統中建立自己的信息,其文件夾爲/proc/binde ,其中包含如下內容:
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爲:
#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驅動程序中使用的另外一個重要的數據結構,數據結構的定義如下所示:
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定義讀寫的數據。
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
開源版本文件的路徑:
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系統中的一個公共庫。
主要文件的路徑如下所示:
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
各個類之間的關係如下所示:
2 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。
3 程序中 Binder 的具體實現
3.1 一個利用接口的具體實現
PermissionController也是libutils中定義的一個有關權限控制的接口,它一共包含兩個文件:IPermissionController.h和IPermissionController.cpp這個結構在所有類的實現中都是類似的。
頭文件IPermissionController.h的主要內容是定義IPermissionController接口和類BnPermissionController:
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。
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()函數如下所示:
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。這個調用過程如下所示:
mRemote()->transact()
Process::self()
IPCThreadState::self()->transact()
writeTransactionData()
waitForResponse()
talkWithDriver()
ioctl(fd, BINDER_WRITE_READ, &bwr)
在IPCThreadState::executeCommand()函數中,實現傳輸操作。