Android binder詳解

原文地址: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
各個類之間的關係如下所示:

image

   

2 Binder 的運作

2.1 Binder 的工作機制

Service Manager是一個守護進程,它負責啓動各個進程之間的服務,對於相關的兩個需要通訊的進程,它們通過調用libutil.so庫實現通訊,而真正通訊的機制,是內核空間中的一塊共享內存。

image

2.2 從應 用程序的角度看Binder

從應用程序的角度看Binder一共有三個方面:
Native 本地:例如BnABC,這是一個需要被繼承和實現的類。
Proxy 代理:例如BpABC,這是一個在接口框架中被實現,但是在接口中沒有體現的類。
客戶端:例如客戶端得到一個接口ABC,在調用的時候實際上被調用的是BpABC

image

本地功能(Bn)部分做的:
    實現BnABC:: BnTransact()
    註冊服務:IServiceManager::AddService
代理部分(Bp)做的:
    實現幾個功能函數,調用BpABC::remote()->transact()
客戶端做的:
    獲得ABC接口,然後調用接口(實際上調用了BpABC ,繼而通過IPC 調用了BnABC ,然後調用了具體的功能)

在程序的實現過程中BnABCBpABC 是雙繼承了接口ABC 。一般來說BpABC 是一個實現類,這個實現類不需要在接口中體現,它實際上負責的只是通訊功能,不執行具體的功能;BnABC 則是一個接口類,需要一個真正工作的類來繼承、實現它,這個類纔是真正執行具體功能的類。

在客戶端中,從ISeriviceManager 中獲得一個ABC 的接口,客戶端調用這個接口,實際上是在調用BpABC ,而BpABC 又通過BinderIPC 機制和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()函數中,實現傳輸操作。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章