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层浅析>

posted @ 2019-12-27 00:18  北落不吉  阅读(4002)  评论(0编辑  收藏  举报