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

  • 相关阅读:
    flume1.7.0的安装与使用
    获取top10
    editplus格式化xml文档
    LOG4J.PROPERTIES配置详解
    Oracle自增列
    javascript 传递引用类型参数
    {JavaScript}栈和堆内存,作用域
    JAVA中String与StringBuffer的区别
    Java中堆和栈的区别(转)
    JAVA错误:org.apache.jasper.JasperException: java.lang.ClassCastException:org.apache.catalina.util.DefaultAnnotationProcessor cannot be cast to org.apach
  • 原文地址:https://www.cnblogs.com/hzl6255/p/12105245.html
Copyright © 2020-2023  润新知