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 ...
随机推荐
- 制作qtopia-2.2.0和qt4文件系统
转自 rootfs_qtopia_qt4.img 1. 解压rootfs_qtopia_qt4-20100816.tar.gz,得到目录rootfs_qtopia_qt4,里面内容比较大,超过了64M ...
- Eclipse报错:java.lang.ClassNotFoundException: ContextLoaderListener(Maven工程)
Eclipse中tomcat部署工程启动后报错: 严重: Error configuring application listener of class org.springframework.web ...
- php Laravel 框架 介绍及安装
Laravel是一套简洁.优雅的PHP Web开发框架(PHP Web Framework).它可以让你从面条一样杂乱的代码中解脱出来:它可以帮你构建一个完美的网络APP,而且每行代码都可以简洁.富于 ...
- Cocos2d—X游戏开发之CCScrollView(滑动视图)(十二)
CCScrollView在Cocos2d-X引擎中主要使用在图片尺寸远大于屏幕尺寸的时候使用. 总体来说,使用起来比较简单. 一个是CCScrollView控件本身,一个是CCScrollViewDe ...
- 【HDOJ】3436 Queue-jumpers
离散化+伸展树. /* 3436 */ #include <iostream> #include <string> #include <map> #include ...
- 【HDOJ】4513 吉哥系列故事——完美队形II
这题目上学期就看了,不过最近发现可以用马拉车来解,而且还是基本算法. 稍微对回文串成立条件变形一下即可. /* 4513 */ #include <iostream> #include & ...
- 织梦内容管理系统(DedeCms) 小说模块insert注入漏洞
漏洞版本: Dedecms 漏洞描述: DedeCms是免费的PHP网站内容管理系统. 织梦内容管理系统(DedeCms) 以简单.实用.开源而闻名,是国内最知名的PHP开源网站管理系统,也是使用用户 ...
- ELK安装配置及nginx日志分析
一.ELK简介1.组成ELK是Elasticsearch.Logstash.Kibana三个开源软件的组合.在实时数据检索和分析场合,三者通常是配合使用,而且又都先后归于 Elastic.co 公司名 ...
- [转]NHibernate之旅(10):探索父子(一对多)关联查询
本节内容 关联查询引入 一对多关联查询 1.原生SQL关联查询 2.HQL关联查询 3.Criteria API关联查询 结语 关联查询引入 在NHibernate中提供了三种查询方式给我们选择:NH ...
- 获取客户端IP地址 via C#
获取客户端IP地址 via C# 说明:本文中的内容是我综合博客园上的博文和MSDN讨论区的资料,再通过自己的实际测试而得来,属于自己原创的内容说实话很少,写这一篇是为了记录自己在项目中做过的事情,同 ...