Android binder介绍(上)
1. 介绍
Binder是Android下基于C/S架构的IPC机制,基于开源OpenBinder
从实现上来说可分为Binder驱动、ServiceManager、Server、Client四个组成部分
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, 远程接口是供客户端调用的接口集
这些类的关系如下图
下面介绍两个重要的宏
/* * 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层浅析>