博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android binder的kernel实现
阅读量:2228 次
发布时间:2019-05-09

本文共 2490 字,大约阅读时间需要 8 分钟。

至少在五六年前就听说过binder机制,但从未想去深入了解。这次忘了是怎么和同事聊起这个东西的不过作为一个码农我想如果连google OS最为精髓的IPC都不知道,真不好以后出去跟人打招呼,于是乎决心了解下,一开始网上搜了些资料,感觉基本上都没讲出些啥东西,没办法只好 read the fucking code, 上周一直忙着签证的事情,没怎么定下心看因而节假日放出大招。

保留一贯的风格不喜欢整篇的paste code,大部分说一些个人的理解
源码靠大家自己

主要分四部分

  • binder的基本框架
  • 为什么需要binder
  • binder的threads
  • binder的transaction
  • binder的服务发布和获取

binder的基本框架

binder是个啥东西?

binder就是个IPC,给进程间通信用的,它的框架包含client,server,servicemanger和binder driver。
前面三个都是user space的进程,线程,后面的binder driver工作在kernel态。

这三个用户态的东西,尤其是servicemanager不是可有可无的,不是说为了应用层的服务框架设计方便所以

多搞出的一个东西,这个binder driver的设计其实是有考虑类似的三个不同角色的分类的。

binder的基本组件

从图上可以看出所有三个用户态的对象在通信的时候都必须要经过binder driver,简单来说每个binder实体都可以通过一个handle来进行标识,但是这个handle是如何获得的就比较复杂了。

可以认为一个process就对应一个binder_proc的实体,这个实体通过open dev/binder这个文件动态创建,所以在C(client), S(server)和M(service manager)启动的初期都必须分别open binder这个文件从而在kernel里面获得binder_proc实体, 但是这个时候并没有handle产生,所以没办法互相通信,这个时候kernel会有一个特殊的handle 0,对应于servicemanager,整个系统只能有一个service manager, 通过M去ioctl前面打开的fd去注册自己为servicemanager,这个特殊的ioctl是BINDER_SET_CONTEXT_MGR,完成了这个特殊的handle的初始化后client和sever就可以向services manager发送命令了,ioctl的cmd为BINDER_WRITE_READ,handle 为0。

为啥要binder

从上面的分析看binder确实只是个IPC,没啥特殊啊。错,由我来带大家慢慢看。

*首先从mem copy上看普通的IPC socket pipe msgQ都需要两次拷贝(shemem不需要拷贝),binder框架下只需要一次copy,发生在用户态到内核态,而内核态到用户态不需要copy。

*binder是有thread概念的,内核态中binder_thread对应到每个binder_proc,下面会详细说
*binder有transaction的概念
*binder中内嵌了服务发布的机制

以上的这些特性非常方便应用层去做基于client server的应用程序的开发。

binder的threads

binder是有thread概念的,内核态中binder_thread对应到每个binder_proc,这就好比我可以在一个进程里面有很多个thread,它们都请求一个server的服务,这个时候每个thread都通过一个fd,就是open /dev/binder时获得的,去和同一个server发请求,此时kernel里面的binder_proc里面就会有一个rbt去记录这些thread的信息,一个thread一个binder_thread结构,并且这边有些限制,比如一个binder_proc中最多能创建多少threads,通过IOCTL中BINDER_SET_MAX_THREADS来进行设置,每次新的线程被create出来后,调用了binder相关的IOCTL后会自动创建binder_thread的结构,但是此时此thread还不能用来收发信息,通过BC_REGISTER_LOOPER使能此thread。

还有个作用是当一个binder_proc对应的binder_thread有在pending的时候(代表threads数目大于实际请求的所以有thread会空闲)userspace不会增加thread,当所有的threads都忙的时候通过BR_SPAWN_LOOPER来告诉用户态此时需要再新建新的thread来处理新的请求。 图中的binder_proc和binder_thread实则为kernel的结构体,为描述方便实体关系放在了user space。
这里写图片描述

binder的transaction

binder中的transaction主要是保证收发的依赖。

举个例子 A 的 A1给 B的 B1发请求,此时B回复必须要用B的B1回复。
首先binder_proc 下面有很多的binder_thread每个代表一个线程,要处理的信息既可以放在thread的todo list也可以放在binder_proc的todo list。
假设A的A1(client 发送请求时必然会选择一个线程发送)要给B发信息,此时M(message)会放在proc对应的todo list里面,此时唤醒B中等待的一个线程(假设为B1)去处理这个消息。
所有的A,A1,B,B1的信息都会放在一个binder_transaction在发送发A,A1会被记录,在接受方 B和B1会记录,这样回城的时候B1会找到A1和A。

binder的bind

handle的生成是通过binder_type_bind binder_type_handle两个flat_binder_object实现的

这里写图片描述

你可能感兴趣的文章
(一)alin‘s mysql学习笔记----概述
查看>>
(二)alin’s mysql学习笔记----mysql的存储引擎
查看>>
(三)alin’s mysql学习笔记----常用的join连接查询
查看>>
(四)alin’s mysql学习笔记----索引简介
查看>>
分布式系统中的幂等性的理解
查看>>
spring的注解开发中的常用注解(一)------@bean @Configuration @ComponentScan @Import @Scope @Lazy
查看>>
(五)alin’s mysql学习笔记----索引性能分析
查看>>
Spring中使用@Transactional注解进行事务管理的时候只有应用到 public 方法才有效
查看>>
springboot整合rabbitmq及rabbitmq的简单入门
查看>>
mysql事务和隔离级别笔记
查看>>
事务的传播属性(有坑点)自调用失效学习笔记
查看>>
REDIS缓存穿透,缓存击穿,缓存雪崩原因+解决方案
查看>>
动态代理实现AOP
查看>>
23种常见的java设计模式
查看>>
关于被final修饰的基本数据类型一些注意事项
查看>>
java Thread中,run方法和start方法的区别
查看>>
在 XML 中有 5 个预定义的实体引用
查看>>
XML 元素是可扩展的
查看>>
避免 XML 属性?针对元数据的 XML 属性
查看>>
XML DOM nodeType 属性值代表的意思
查看>>