Learn && Live
虚度年华浮萍于世,勤学善思至死不渝
前言
Hey,欢迎阅读Connor学Android系列,这个系列记录了我的Android原理知识学习、复盘过程,欢迎各位大佬阅读斧正!原创不易,转载请注明出处:http://t.csdn.cn/yfoPe,话不多说我们马上开始!
前排声明:本篇主要参考了Carson的两篇博文,文章连接:https://blog.csdn.net/carson_ho/article/details/73560642、https://www.jianshu.com/p/719fc4758813。另外十分推荐大家去看Carson的博客学习Android及相关知识,讲的很清楚很明白!
1.Binder是什么?
2.预备知识
1.Linux进程空间划分
2.跨进程通信基本原理
(1)进程1通过系统调用,将需发送的数据拷贝到Linux进程的内核空间中的缓存区
(2)内核服务程序唤醒接收进程的接收线程,通过系统调用将数据发送到进程2的用户空间中
缺点
(1)效率低下:两次数据拷贝
(2)接受数据的缓存由接收方提供,但接收方不知道到底要多大的缓存
3.内存映射
建立进程的虚拟内存区域 <==> 1个磁盘上的对象(普通文件/匿名文件)之间的映射关系
多个进程的虚拟内存区域与1个共享对象建立映射,其中1个进程对该虚存区域进行写操作,会将这一操作映射到共享对象,在映射到其他关联的进程虚存区域上,可减少数据拷贝的次数
3.Binder跨进程通信机制模型
模型原理图
模型原理步骤说明
(1)注册服务
1.Server进程向Binder驱动发起服务注册请求
2.Binder驱动将注册请求转发给Service Manager进程
3.Service Manager进程添加该Server进程
(2)获取服务
1.Client向Binder驱动发起获取服务器请求,传递要获取的服务名称
2.Binder驱动将请求转发给Service Manager进程
3.ServiceManager查找到Client需要的Server对应的服务信息
4.通过Binder驱动向Client进程返回服务信息
(3)使用服务
1.实现内存映射
① Binder驱动创建一块接收缓存区
② 建立地址映射:根据Service Manager进程中的Server信息找到对应的Server进程,实现内核缓存区和Server进程用户空间地址同时映射到同一接收缓存区中
2.Client进程将参数数据发送到Server进程
① Client进程调用 copy_from_user 发送数据到内核空间中的缓存区(当前线程挂起),同时由于内存映射,Server进程也会收到数据,即完成跨进程通信
② Binder驱动通知Server进程解包
3.Server进程根据Client进程的要求调用目标方法
① 收到Binder驱动通知后,Server进程从线程池中取出线程,进行数据解包并调用目标方法
② 将最终执行结果写入到自己的共享内存中
4.Server进程将目标方法的执行结果返回Client进程
① 将最终结果卸任存在映射的用户空间内存区域,内存映射,同时发送到了内核缓存区
② Binder驱动通知Client进程获取返回结果(唤醒之前被挂起的线程)
③ Client进程调用copy_to_user从内核缓存区接收Server进程返回的数据
优点
(1)仅拷贝1次,传输效率高
(2)为接收进程分配了不确定大小的接收缓存区
补充
(1)Client进程、Server进程、Service Manager进程之间必须通过Binder交互,不可直接交互
原因:Client进程、Server进程、Service Manager进程属于用户空间,Binder属于内核空间
(2)Binder、Service Manager进程属于Android基础架构,Client进程、Server进程属于应用层,需自己实现
(3)Server进程会创建很多线程来处理Binder请求。Binder模型的线程管理采用Binder驱动的线程池,并由Binder驱动自身进行管理
进程属于Android基础架构,Client进程、Server进程属于应用层,需自己实现