Android - Binder驱动
Binder机制介绍

- 一次数据拷贝
 - Client/Server通信模型
 - 既可用作进程间通信,也可用作进程内通信
 

- 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内核缓冲区所对应的物理页面是按需要分配的,一开始只有一个物理页被被映射
 

- 用户空间:0G ~ 3G
 - 内核空间:3G ~ 4G。其中,3G ~ (3G + 896M)范围的地址是用来映射连续的物理页面的,这个范围的虚拟地址和对应的实际物理地址有着简单的对应关系,即对应0~896M的物理地址空间;而(3G + 896M) ~ (3G + 896M + 8M)是安全保护区域(例如,所有指向这8M地址空间的指针都是非法的);因此使用(3G + 896M + 8M) ~ 4G地址空间来映射非连续的物理页面
 

Client/Server通信模型
Service Manager注册及其代理获得

- 打开/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代理获取

Service注册

Client和Server的通信过程

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代理
 
- 一个进程向另外一个进程发送文件描述符
 

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两个引用计数
 

- 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可以处理其它新的请求
 



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 ...
 
随机推荐
- Android ListView中 每一项都有不同的布局
			
实现代码 Adapter的代码 其中:ViewHolder分别是三个不同的布局,也就是ListView中每一项的布局 TYPE_1...是三种类型. 在使用不同布局的时候,getItemViewTyp ...
 - CTO的眼界到底有多宽?
			
CTO的眼界到底有多宽? [CSDN独家报道]在各大企业中,CTO (Chief Technology Officer,首席技术官)有着雄厚的技术实力,掌握着企业核心技术,是软件开发项目中最重要的人 ...
 - POJ_3104_Drying_(二分,最小化最大值)
			
描述 http://poj.org/problem?id=3104 n件衣服,第i件衣服里面有水a[i],自然风干每分钟干1个水,用吹风机每分钟干k个水,但是同时只能对一件衣服使用吹风机,求干完所有衣 ...
 - Hadoop RPC源码阅读-客户端
			
Hadoop版本Hadoop2.6 RPC主要分为3个部分:(1)交互协议(2)客户端(3)服务端 (2)客户端 先展示RPC客户端实例代码 public class LoginController ...
 - WCF性能优势体现 【转】
			
WCF性能优势决定了其受欢迎程度,这些优势主要都体现在:统一性:互操作性:安全与可信赖:兼容性等方面. WCF是使用托管代码建立和运行面向服务(Service Oriented)应用程序的统一框架. ...
 - What is happening in Crockford's object creation technique?
			
What is happening in Crockford's object creation technique? http://stackoverflow.com/questions/27660 ...
 - Bzoj 1976: [BeiJing2010组队]能量魔方 Cube  最小割,最大流
			
1976: [BeiJing2010组队]能量魔方 Cube Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 879 Solved: 304[Submi ...
 - BWT(Burrows-Wheeler Transformation)的讲解及java实现
			
BWT(Burrows-Wheeler Transformation) 1.什么是BWT 压缩技术主要的工作方式就是找到重复的模式,进行紧密的编码. BWT(Burrows–Wheeler_trans ...
 - Using OpenCV with gcc and CMake
			
Using OpenCV with gcc and CMake Note We assume that you have successfully installed OpenCV in your w ...
 - 【转】【opencv】仿射变换
			
仿射变换 目标 在这个教程中你将学习到如何: 使用OpenCV函数 warpAffine 来实现一些简单的重映射. 使用OpenCV函数 getRotationMatrix2D 来获得一个 旋转矩阵 ...