Android - Binder驱动
Binder机制介绍
![](http://images2015.cnblogs.com/blog/947400/201605/947400-20160526104407584-993452939.png)
- 一次数据拷贝
- Client/Server通信模型
- 既可用作进程间通信,也可用作进程内通信
![](http://images2015.cnblogs.com/blog/947400/201605/947400-20160526104408522-489428153.jpg)
- Client、Server和Service Manager实现在用户空间中,Binder驱动程序实现在内核空间中
- Binder驱动程序和Service Manager在Android平台中已经实现,开发者只需要在用户空间实现自己的Client和Server
- Binder驱动程序提供设备文件/dev/binder与用户空间交互,Client、Server和Service Manager通过open和ioctl文件操作函数与Binder驱动程序进行通信
- Client和Server之间的进程间通信通过Binder驱动程序间接实现
- Service Manager是一个守护进程,用来管理Server,并向Client提供查询Server接口的能力
一次数据拷贝
- 4M内核缓冲区所对应的物理页面除了映射在内核空间之外,还会被映射在进程的用户空间(同时使用进程虚拟地址空间和内核虚拟地址空间来映射同一个物理页面)
- 4M内核缓冲区所对应的物理页面是按需要分配的,一开始只有一个物理页被被映射
![](http://images2015.cnblogs.com/blog/947400/201605/947400-20160526104409553-32834501.jpg)
- 用户空间:0G ~ 3G
- 内核空间:3G ~ 4G。其中,3G ~ (3G + 896M)范围的地址是用来映射连续的物理页面的,这个范围的虚拟地址和对应的实际物理地址有着简单的对应关系,即对应0~896M的物理地址空间;而(3G + 896M) ~ (3G + 896M + 8M)是安全保护区域(例如,所有指向这8M地址空间的指针都是非法的);因此使用(3G + 896M + 8M) ~ 4G地址空间来映射非连续的物理页面
![](http://images2015.cnblogs.com/blog/947400/201605/947400-20160526104410163-1246805380.jpg)
Client/Server通信模型
Service Manager注册及其代理获得
![](http://images2015.cnblogs.com/blog/947400/201605/947400-20160526104410897-2139669369.jpg)
- 打开/dev/binder文件:open("/dev/binder", O_RDWR);
- 建立128K内存映射:mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
- 通知Binder驱动程序它是守护进程:binder_become_context_manager(bs);
- 进入循环等待请求的到来:binder_loop(bs, svcmgr_handler);
Service代理获取
![](http://images2015.cnblogs.com/blog/947400/201605/947400-20160526104411866-1132619642.png)
Service注册
![](http://images2015.cnblogs.com/blog/947400/201605/947400-20160526104413131-1685367855.jpg)
Client和Server的通信过程
![](http://images2015.cnblogs.com/blog/947400/201605/947400-20160526104414334-1909043348.jpg)
Binder进程间通信机制的Java接口
- 每一个Java层的Binder本地对象(Binder)在C++层都对应有一个JavaBBinder对象,后者是从C++层的BBinder继承下来的
- 每一个Java层的Binder代理对象(BinderProxy)在C++层都对应有一个BpBinder对象
- 于是Java层的Binder进程间通信实际上就是通过C++层的BpBinder和BBinder来进行的,与C++层的Binder进程间通信 一致
Binder对象
- Server进程主动向Client进程发送Service (匿名Service )
- Server进程向Service Manager进程注册Service
- 一个Client向另外一个进程发送Service代理
- 一个进程向另外一个进程发送文件描述符
![](http://images2015.cnblogs.com/blog/947400/201605/947400-20160526104415663-906709765.jpg)
Binder对象的引用计数
- BBinder:位于用户空间,通过智能指针管理,有mStrong和mWeak两个引用计数
- BpBinder:位于用户空间,通过智能指针管理,有mStrong和mWeak两个引用计数
- binder_node:位于内核空间,有internal_strong_refs、local_weak_refs和local_strong_refs三个引用计数,以及一个binder_ref引用列表refs
- binder_ref:位于内核空间,有strong和weak两个引用计数
![](http://images2015.cnblogs.com/blog/947400/201605/947400-20160526104416616-316473920.jpg)
- Binder对象引用关系小结:
-binder_node和binder_ref运行在内核空间
- 内核空间足够健壮,保证binder_node和binder_ref不会异常销毁
- 用户空间不够健壮,BBinder和BpBinder可能会异常销毁
- BpBinder异常销毁不会引发致命问题,但是BBinder异常销毁会引发致命问题
- 需要有一种方式来监控BBinder和BpBinder的异常销毁:
- 所有执行Binder IPC的进程都需要打开/dev/binder文件
- 进程异常退出的时候,内核保证会释放未正常关闭的它打开的/dev/binder文件,即调用与/dev/binder文件所关联的release回调函数
- Binder驱动通过实现/dev/binder文件的release回调函数即可监控Binder对象的异常销毁,进而执行清理工作
- Client进程从Binder驱动获得一个BpBinder
- Client进程向Binder驱动注册一个死亡通知,该死亡通知与上述BpBinder所引用的BBinder相关联
- Binder驱动监控到BBinder所在进程异常退出的时候,检查该BBinder是否注册有死亡通知
- Binder驱动向注册的死亡通知所关联的BpBinder所运行在的Client进程发送通知
- Client进程执行相应的清理工作
- 在源进程中找到对应的binder_node。如果不存在,则创建。
- 根据上述binder_node在目标进程中找到对应的binder_ref。如果不存在,则创建。
- 增加上述binder_ref的强引用计数和弱引用计数(智能指针)
- 构造一个类型为BINDER_TYPE_HANDLE的flat_binder_object对象。
- 将上述flat_binder_object对象发送给目标进程。
- 在源进程中找到对应的binder_node。如果不存在,则创建。
- 根据上述binder_node在目标进程中找到对应的binder_ref。如果不存在,则创建。
- 增加上述binder_ref的弱引用计数。(智能指针)
- 构造一个类型为BINDER_TYPE_WEAK_HANDLE的flat_binder_object对象。
- 将上述flat_binder_object对象发送给目标进程。
- 如果上述binder_ref所引用的binder_node所在进程就是目标进程:
- 增加上述binder_node的强引用计数和弱引用计数(智能指针)
- 构造一个类型为BINDER_TYPE_BINDER的flat_binder_object
- 将上述flat_binder_object发送给目标进程
- 如果上述binder_ref所引用的binder_node所在进程不是目标进程:
- 为目标进程创建一个binder_ref,该binder_ref与上述binder_ref引用的是同一个binder_node
- 增加上述新创建的binder_ref的强引用计数和弱引用计数(智能指针)
- 构造一个类型为BINDER_TYPE_HANDLE的flat_binder_object
- 将上述flat_binder_object发送给目标进程
- 如果上述binder_ref所引用的binder_node所在进程就是目标进程:
- 增加上述binder_node的弱引用计数(智能指针)
- 构造一个类型为BINDER_TYPE_WEAK_BINDER的flat_binder_object
- 将上述flat_binder_object发送给目标进程
- 如果上述binder_ref所引用的binder_node所在进程不是目标进程:
- 为目标进程创建一个binder_ref,该binder_ref与上述binder_ref引用的是同一个binder_node
- 增加上述新创建的binder_ref的弱引用计数(智能指针)
- 构造一个类型为BINDER_TYPE_WEAK_HANDLE的flat_binder_object
- 将上述flat_binder_object发送给目标进程
- 在源进程中找到对应的struct file结构体
- 将上述struct file结构体 保存在目标进程的打开文件列表中
- 构造一个类型为BINDER_TYPE_FD的flat_binder_object
- 将上述flat_binder_object发送给目标进程
Binder线程池
- 每一个Server进程在启动的时候都会创建一个Binder线程池,并且向里面注册一个Binder线程
- 之后Server进程可以无限地向Binder线程池注册新的Binder线程
- Binder驱动发现Server进程没有空间的Binder线程时,会主动向Server进程请求注册新的Binder线程(Binder驱动主动请求Server进程注册新的Binder线程的数量可以由Server进程设置,默认是16)
- 在Server进程中,Client进程发送过来的Binder请求由Binder线程进行处理
Binder线程调度机制
- 在Binder驱动中,每一个Server进程都有一个todo list,用来保存Client进程发送过来的请求,这些请求可以由其Binder线程池中的任意一个空闲线程处理
- 在Binder驱动中,每一个Binder线程也有一个todo list,用来保存Client进程发送过来的请求,这些请求只可以由该Binder线程处理
- Binder线程没事做的时候,就睡眠在Binder驱动中,直至它所属的Server进程的todo list或者它自己的todo list有新的请求为止
- 每当Binder驱动将Client进程发送过来的请求保存在Server进程的todo list时,都会唤醒其Binder线程池的空闲Binder线程池,并且让其中一个来处理
- 每当Binder驱动将Client进程发送过来的请求保存在Binder线程的todo list时,都会将其唤醒来处理
同步请求优先于异步请求
- 同一时刻,一个BBinder只能处理一个异步请求
- 第一个异步请求将被保存在目标进程(server进程)的todo list中
- 第一个异步请求未被处理前,其它的异步请求将被保存在对应的 binder_node的async todo list中
- 第一个异步请求被处理之后,第二个异步请求将从binder_node的async todo list转移至目标进程的todo list等待处理
- 依次类推……
- 源线程的优先级
- 目标线程的优先级
- 目标binder_node的最小优先级(注册Service时设置)
- Binder线程处理同步请求时的优先级:取{源线程,目标binder_node,目标线程}的最高优先级;保证目标线程以不低于源线程优先级或者binder_node最小优先级的优先级运行
- Binder线程处理异步请求时的优先级:取{目标binder_node,目标线程}的最高优先级;保证目标线程以不低于binder_node最小优先级的优先级运行
Binder线程的事务(binder_transaction)堆栈
- -源进程P1的线程A向目标进程发起了一个请求T1,该请求被分发给目标进程P2的线程B处理
- -源进程P1的线程A等待目标进程P2的线程B处理处理完成请求T1
- -目标进程P2的线程B在处理请求T1的过程中,需要向源进程P1发起另一个请求T2
- -源进程P1除了线程A是处于空闲等待状态之外,还有另外一个线程C处于空闲等待状态
- -如果分发给线程C处理,则线程A仍然是处于空闲等待状态
- -如果分发给线程A处理,则线程 C可以处理其它新的请求
![](http://images2015.cnblogs.com/blog/947400/201605/947400-20160526104417288-451370607.png)
![](http://images2015.cnblogs.com/blog/947400/201605/947400-20160526104418225-1613356225.jpg)
![](http://images2015.cnblogs.com/blog/947400/201605/947400-20160526104418913-1434000751.png)
Android - Binder驱动的更多相关文章
- Android系统--Binder系统具体框架分析(二)Binder驱动情景分析
Android系统--Binder系统具体框架分析(二)Binder驱动情景分析 1. Binder驱动情景分析 1.1 进程间通信三要素 源 目的:handle表示"服务",即向 ...
- Android Binder实现浅析-Binder驱动
简介 Android是如何实现跨进程通信的,大家熟悉的Binder是什么,怎么设计的,进程间的数据如何发送接收的.本文将以及解析,并对Binder驱动实现.Native层实现.Java层实现三块做一个 ...
- 理解 Android Binder 机制(一):驱动篇
Binder的实现是比较复杂的,想要完全弄明白是怎么一回事,并不是一件容易的事情. 这里面牵涉到好几个层次,每一层都有一些模块和机制需要理解.这部分内容预计会分为三篇文章来讲解.本文是第一篇,首先会对 ...
- Android面试官:说说你对 Binder 驱动的了解?
面试官提了一个问题:说说你对 binder 驱动的了解.这个问题虽有些 "面试造火箭" 的无奈,可难点就是亮点.价值所在,是筛选面试者的有效手段.如果让你回答,你能说出多少呢?我们 ...
- [转]Android Binder设计与实现 - 设计篇
摘要 Binder是Android系统进程间通信(IPC)方式之一.Linux已经拥有管道,system V IPC,socket等IPC手段,却还要倚赖Binder来实现进程间通信,说明Binder ...
- (转)Android Binder设计与实现 – 设计篇
原文地址(貌似已打不开):Android Binder设计与实现 – 设计篇 ------------------------------------------------------------- ...
- 图解Android - Binder 和 Service
在 Zygote启动过程 一文中我们说道,Zygote一生中最重要的一件事就是生下了 System Server 这个大儿子,System Server 担负着提供系统 Service的重任,在深入了 ...
- Android Binder设计与实现 - 设计篇
要 Binder是Android系统进程间通信(IPC)方式之一.Linux已经拥有管道,system V IPC,socket等IPC手段,却还要倚赖Binder来实现进程间通信,说明Binder具 ...
- Android - Ashmem驱动
以下资料摘录整理自老罗的Android之旅博客,是对老罗的博客关于Android底层原理的一个抽象的知识概括总结(如有错误欢迎指出)(侵删):http://blog.csdn.net/luosheng ...
随机推荐
- 【UVA 11183】 Teen Girl Squad (定根MDST)
[题意] 输入三元组(X,Y,C),有向图,定根0,输出MDST. InputThe first line of input gives the number of cases, N (N < ...
- Multi-Die系统介绍
一个典型的存储系统一般是有几片NAND存储器组成的.一般会使用8-bit的总线,用来将不同的存储器与控制器进行连接,如图2.32所示.一个系统中多片NAND的存储系统可以提高存储容量,同时还可以提高读 ...
- 基于Delphi的Socket I/O模型全接触 good
老陈有一个在外地工作的女儿,不能经常回来,老陈和她通过信件联系.他们的信会被邮递员投递到他们的信箱里. 这和Socket模型非常类似.下面我就以老陈接收信件为例讲解Socket I/O模型. 一:se ...
- lsof 拥有更多的功能
lsof 拥有更多的功能# lsof -i 看系统中有哪些开放的端口,哪些进程.用户在使用它们,比 netstat -lptu 的输出详细. # lsof -i 4 查看IPv4类型的进程COMMA ...
- Linux中修改环境变量及生效方法
在/etc/profile文件中添加变量[对所有用户生效(永久的)] 用VI在文件/etc/profile文件中增加变量,该变量将会对Linux下所有用户有效,并且是“永久的”. 要让刚才的修改马上生 ...
- bzoj1899
显然如果只有一个窗口,是一道贪心的题目,直接让吃饭慢的排在前面即可 两个窗口的话,我们还是根据这个原则 先对吃饭时间降序排序,然后这是一个dp 假如设当前处理到第i个人,当在窗口1的打饭时间确定了,窗 ...
- android webview js交互 第一节 (java和js交互)
转载请注明出处 挺帅的移动开发专栏 http://blog.csdn.net/wangtingshuai/article/details/8631835 在androi ...
- python爬虫学习(1)__抓取煎蛋图片
#coding=utf-8 #python_demo 爬取煎蛋妹子图在本地文件夹 import requests import threading import time import os from ...
- 一起来说 Vim 语
作为一款古老而具有持久生命力的编辑器,vim 自有它的强大之处.很多人觉得 Vim 的学习曲线太陡峭了,为了能够把 Vim 用得风生水起,不得不记忆大量的命令.如果你是 Vim 新手,刚入门就开始面对 ...
- 手动进行Excel数据和MySql数据转换
今天是全国数学建模比赛,同学选的一个题目需要对一个large的Excel表格进行统计,好哥们儿嘛--便帮助他完成了数据从Excel到MySql的转化.记下具体步骤分享给大家,也免得大家到网上到处乱找了 ...