Android binder介紹(上)


1. 介紹

Binder是Android下基於C/S架構的IPC機制,基於開源OpenBinder

從實現上來說可分為Binder驅動、ServiceManager、Server、Client四個組成部分

binder_framework

2. Binder驅動

Binder驅動代碼主要位於drivers/android目錄

2.1 數據結構

數據結構 說明
binder_device binder設備,系統初始化時會定義binder、hwbinder、vndbinder三個設備
binder_context binder上下文,每個binder設備包含一個上下文結構

binder_proc

binder進程記錄,每個打開binder設備的進程均包含該結構,用來記錄該進程的各種信息和狀態。例如:線程表、binder節點表、節點引用表
binder_thread binder線程,記錄了線程相關的信息,例如需要完成的任務等
binder_node binder節點
binder_transaction binder事務
binder_buffer binder緩沖區,由mmap創建,用於binder事務
binder_alloc binder proc的地址空間
binder_ref binder引用

2.2 初始化

binder_init()
    /* 
     * 創建如下目錄和文件
     *   目錄
     *       /sys/kernel/debug/binder
     *       /sys/kernel/debug/binder/proc
     *   文件
     *       $(BINDER)/state                  -- 記錄狀態信息
     *       $(BINDER)/stats                  -- 記錄統計信息
     *       $(BINDER)/transactions           -- 記錄transaction相關信息
     *       $(BINDER)/transaction_log        -- 記錄transaction日志相關信息
     *       $(BINDER)/failed_transaction_log -- 記錄失敗的transaction日志相關信息
     *   文件讀取函數依次為
     *       binder_state_show()
     *       binder_stats_show()
     *       binder_transactions_show()
     *       binder_transactions_log_show()
     *       -
     *   $(BINDER) = /sys/kernel/debug/binder/
     */
    debugfs_create_dir("binder")
    debugfs_create_dir("proc")
    debugfs_create_dir("state")
    debugfs_create_dir("stats")
    debugfs_create_dir("transactions")
    debugfs_create_dir("transaction_log")
    debugfs_create_dir("failed_transaction_log")

    /* 
     * 注冊/dev/binder, /dev/hwbinder, /dev/vndbinder設備
*/
    init_binder_device()
        misc_register(binder_fops)

    /* binder設備操作集 */
    static const struct file_operations binder_fops = {
        .owner          = THIS_MODULE,
        .poll           = binder_poll,
        .unlocked_ioctl = binder_ioctl,
        .compat_ioctl   = binder_ioctl,
        .mmap           = binder_mmap,
        .open           = binder_open,
        .flush          = binder_flush,
        .release        = binder_release,
    };

2.3 打開

當應用打開一個binder設備時,在內核中中會執行binder_open

- 分配並創建binder_proc結構
- 初始化binder_proc的context、tsk、todo、default_priority、context、alloc等成員變量
- 將binder_proc保存到file::private_data結構中, 以之后的mmap、ioctl中獲取
- 將binder_proc::proc_node插入全局變量binder_procs中
- 創建/sys/kernel/debug/binde/proc/`pid`文件

2.4 映射

當應用對binder設備執行mmap時,mmap首先會在調用進程的虛擬地址空間(struct vm_area_struct vma)創建一個地址到文件的映射,隨后在內核中會執行binder_mmap

- 初始化vma的vm_flags、vm_ops、vm_private_data成員變量
- 調用binder_alloc_mmap_handler(struct binder_alloc, struct vm_area_struct)建立映射
-- 通過get_vm_area()在內核vmalloc區域獲取vma相同大小連續空間(struct vm_struct area)
-- 根據area初始化binder_alloc的buffer、buffer_size、user_buffer_offset等成員變量
-- 通過kzalloc分配物理頁表項(struct page)並賦值給binder_alloc::binder_lru_page
-- 通過kzalloc分配一個binder_buffer結構用來分配物理頁,對vmalloc區域建立頁表映射關系

2.5 操作

應用執行ioctl時在內核執行binder_ioctl

命令 參數 含義
BINDER_WRITE_READ struct binder_write_read 向驅動讀取和寫入數據.可同時讀和寫

BINDER_SET_MAX_THREADS

int 設置線程池的最大的線程數,達到上限后驅動將不會在通知應用層啟動新線程

BINDER_SET_CONTEXT_MGR

- 將本進程設置為binder系統的管理進程,servicemanager進程使用,這個命令且只能調用一次

BINDER_THREAD_EXIT

- 通知驅動當前線程即將退出,以便驅動清理該線程相關的數據
BINDER_VERSION struct binder_version 獲取binder的版本號

值得一說的是首次調用ioctl時會為進程創建一個線程, 具體可參考binder_get_thread()

3. servicemanager

3.1 介紹

servicemanager由init在post-fs階段啟動,Android N以后由三個服務組成

- servicemanager: 使用/dev/binder設備,用於framework/app processes IPC
- hwservicemanager: 使用/dev/hwbinder設備,用於framework/vendor processes IPC
- vndservicemanager: 使用/dev/vndbinder設備,用於vendor/vendor processes IPC

servicemanager/vndservicemanager代碼位於frameworks/native/cmds/servicemanager
hwservicemanager代碼位於system/hwservicemanager(此處不分析)

servicemanager集中管理系統內的所有服務,提供了注冊、查找、遍歷服務的功能

3.2 代碼分析

/*
 * 服務列表
 * struct svcinfo *svclist
 */
struct svcinfo
{
    struct svcinfo *next;
    uint32_t handle;
    struct binder_death death;
    int allow_isolated;
    uint32_t dumpsys_priority;
    size_t len;
    uint16_t name[0];
};

main()
    binder_open()
        // 打開binder設備
         open("/dev/binder" or "dev/vndbinder")
        // 獲取內核binder版本
         ioctl(binder_fd, BINDER_VERSION, )
        // 映射128k大小空間
         mmap(128 * 1024)

    // 設置binder上下文管理者
    ioctl(binder_fd, BINDER_SET_CONTEXT_MGR, 0)

    // selinux相關設置
    ...

    // 進入主循環
    binder_loop()
        // 讀取請求
         ioctl(binder_fd, BINDER_WRITE_READ, )
        // 事件處理
         binder_parse()
            // 處理BR_TRANSACTION事件
              svcmgr_handler()
                // 查找服務
                  do_find_service()
                // 注冊服務
                  do_add_service()

4. Native Binder

Android中實現了如下native binder庫,

- libbinder: 用於servicemanager/vndservicemanager, 代碼位於frameworks/native/libs/binder
- libhwbinder: 用於hwservicemanager, 代碼位於system/libhwbinder

這里主要介紹一下libbinder庫、IServiceManager、libbinder使用實例

4.1 基礎類

/*
 * I: Interface, 服務接口
 * B: Binder
 * n: native, 服務方, 也即本地端
 * p: proxy, 代表了調用方, 也即遠程端
 */
android::BpRefBase      - RefBase的子類, 提供remote()方法獲取遠程Binder
android::IBinder        - Binder抽象接口, BBinder和BpBinder都是該類的子類
android::IInterface:    - Binder服務接口基類, Binder服務通常需要同時提供本地接口和遠程接口
android::IPCThreadState - 使用Binder的線程, 封裝了與Binder驅動通信的邏輯
android::ProcessState   - 使用Binder的進程

android::BBinder        - 本地Binder, 實現接受請求的接口
android::BpBinder       - 遠程Binder, 實現發送請求的接口
android::BnInterface    - 本地接口的基類, 繼承自BBinder, 本地接口是需要服務中真正實現的接口集
android::BpInterface    - 遠程接口的基類, 繼承自Bpinder, 遠程接口是供客戶端調用的接口集

這些類的關系如下圖

binder_class

下面介紹兩個重要的宏

/*
 * DECLARE_META_INTERFACE定義了
 * - descriptor
 * - asInterface()
 * - getInterfaceDescriptor()
 * - constructor()/destructor()
 */

IMPLEMENT_META_INTERFACE(xxx, xxxdesc)
#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();                                            \

/*
 * IMPLEMENT_META_INTERFACE實現了
 * - descriptor
 * - asInterface()
 * - getInterfaceDescriptor()
 * - constructor()/destructor()
 */
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                       \
    const ::android::String16 I##INTERFACE::descriptor(NAME);           \
    const ::android::String16&                                          \
            I##INTERFACE::getInterfaceDescriptor() const {              \
        return I##INTERFACE::descriptor;                                \
    }                                                                   \
    ::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;                                                    \
    }                                                                   \
    I##INTERFACE::I##INTERFACE() { }                                    \
    I##INTERFACE::~I##INTERFACE() { }                                   \

4.2 IServiceManager

android::IServiceManager充當了servicemanager的代理接口,用來訪問servicemanager提供的服務
可通過defaultServiceManager()來獲取IServiceManager實例

class IServiceManager : public IInterface
{
public:
    sp<IBinder>         getService(const String16& name);
    sp<IBinder>         checkService(const String16& name);
    status_t addService(const String16& name, const sp<IBinder>& service,
                                bool allowIsolated, int dumpsysFlags)
    Vector<String16> listServices(int dumpsysFlags);
};

/*
 * defaultServiceManager = new BpServiceManager(new BpBinder(0));
 */
sp<IServiceManager> defaultServiceManager();

defaultServiceManager()
    ProcessState::self()
        new ProcessState("/dev/binder")
            open_driver("/dev/binder")
            mmap()
    ProcessState::getContextObject(NULL)
        getStrongProxyForHandle(0)
            BpBinder::create(NULL)
                new BpBinder(NULL, uid)
    interface_cast<IserviceManager>(new BpBinder())
        IserviceManager::asInterface(new BpBinder())
            new BpServiceManager(new BpBinder())
                BpInterface::BpInterface()
                    BpRefBase::BpRefBase()

4.3 實例

這里介紹以下使用libbinder實現native server和client的方法,以IFixMe為例

接口實現

// .h
namespace android {
enum { 
    COMMAND_ONE = IBinder::FIRST_CALL_TRANSACTION, 
    COMMAND_TWO
}; 
class IFixMe: public IInterface
{
public:
    DECLARE_META_INTERFACE(FixMe)
    
    virtual int  func1(const String16& str1) = 0;
    virtual void func2() = 0;
}
}

//.cpp
using namespace android;
IMPLEMENT_META_INTERFACE(FixMe, "FixMeDesc");

Server實現

// .h
class BnFixMe : public BnInterface<IFixMe>
{
public:
    virtual status_t onTransact(uint32_t code, const Parcel& data, 
                                Parcel* reply, uint32_t flags = 0); 
};

// .cpp
status_t BnFixMe::onTransact(uint32_t code,const Parcel & data,
                             Parcel * reply, uint32_t flags)
{
    switch(code)
    {
        case COMMAND_ONE:
        {
            CHECK_INTERFACE(IFixMe, data, reply);
            const char *str = data.readCString();
            // Do something with input string
            reply->writeNoException();
            reply->writeInt32(ret);
            return NO_ERROR;
        }
        case COMMAND_TWO:
        {
            CHECK_INTERFACE(IFixMe, data, reply);
            // Do something
            reply->writeNoException();
            return NO_ERROR;
        }
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}

Client實現

// *.cpp
class BpFixMe : public BpInterface<IFixMe>
{
public:
    BpFixMe(const sp<IBinder>& impl) : BpInterface<IFixMe>(impl){};
    int func1(const char *str)
    {
        Parcel data, reply;  
        data.writeInterfaceToken(IFixMe::getInterfaceDescriptor());  
        data.writeCString(str);
        remote()->transact(COMMAND_ONE, data, &reply);

        int32_t exception = reply.readExceptionCode();
        return reply.readInt32();
    }

    void func2()
    {
        Parcel data, reply;  
        data.writeInterfaceToken(IFixMe::getInterfaceDescriptor());  
        remote()->transact(COMMAND_TWO, data, &reply);
    }
};

測試程序

#define SERVICE_NAME "FixMe"

// server test binary
int main()
{
    defaultServiceManager()->addService(String16(SERVICE_NAME), new BnFixMe());
    ProcessState::self()->startThreadPool();  
    IPCThreadState::self()->joinThreadPool();  
 
    return 0;  
}

// client test binary
int main()
{
    sp<IBinder> binder = defaultServiceManager()->getService(String16(SERVICE_NAME));  
    // equal IFixMe::asInterface(binder)
    sp<IFixMe> service = interface_cast<IFixMe>(binder);  
    service->func1("giveme5")
    service->func2()

    return 0;  
}

TIPS: 通常把接口實現、Server實現、Client實現放在一起

其他實例可參考MediaPlayerService、<NativeBinderTest>、<Android-HelloWorldService>、<native-service>

參考:
<理解Android Binder機制>
<Binder機制情景分析之深入驅動>
<Binder機制情景分析之native層淺析>


免責聲明!

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



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