河南省国基建设集团有限公司网站,合肥网页设计就业,学院网站建设情况,网站开发做账目录
1. Binder到底是什么#xff1f;
2. 知识储备
2.1 进程空间划分
2.2 进程隔离 跨进程通信#xff08; IPC #xff09;
2.3 内存映射
2.3.1 作用
2.3.2 实现过程
2.3.3 特点
2.3.4 应用场景
2.3.5 实例讲解
① 文件读 / 写操作
② 跨进程通信
3. Bi…目录
1. Binder到底是什么
2. 知识储备
2.1 进程空间划分
2.2 进程隔离 跨进程通信 IPC
2.3 内存映射
2.3.1 作用
2.3.2 实现过程
2.3.3 特点
2.3.4 应用场景
2.3.5 实例讲解
① 文件读 / 写操作
② 跨进程通信
3. Binder 跨进程通信机制 模型
3.1 模型原理图
3.2 模型组成角色说明
3.3 模型原理步骤说明
3.4 额外说明
4. Binder机制 在Android中的具体实现原理
步骤1注册服务
步骤2获取服务
步骤3使用服务
步骤1 Client进程 将参数整数a和b发送到Server进程
步骤2Server进程根据Client进要求 调用 目标方法即加法函数
步骤3Server进程 将目标方法的结果即加法后的结果返回给Client进程
5. 优点 1. Binder到底是什么
网上有很多对Binder的定义Binder是跨进程通信方式、它实现了IBinder接口是连接 ServiceManager的桥
我认为对于Binder的定义在不同场景下其定义不同 在本文的讲解中按照 大角度 - 小角度 去分析Binder即
先从机制、模型的角度去分析整个Binder跨进程通信机制的模型其中会详细分析模型组成中的 Binder驱动
再从源码实现角度分析 Binder在 Android中的具体实现从而全方位地介绍 Binder。
2. 知识储备
在讲解Binder前我们先了解一些Linux的基础知识
2.1 进程空间划分
一个进程空间分为 用户空间 内核空间Kernel即把进程内 用户 内核 隔离开来
二者区别
进程间用户空间的数据不可共享所以用户空间 不可共享空间进程间内核空间的数据可共享所以内核空间 可共享空间
所有进程共用1个内核空间
进程内 用户空间 内核空间 进行交互 需通过 系统调用主要通过函数
copy_from_user将用户空间的数据拷贝到内核空间copy_to_user将内核空间的数据拷贝到用户空间 2.2 进程隔离 跨进程通信 IPC
进程隔离 为了保证 安全性 独立性一个进程 不能直接操作或者访问另一个进程即Android的进程是相互独立、隔离的跨进程通信 IPC 即进程间需进行数据交互、通信跨进程通信的基本原理 a. 而Binder的作用则是连接 两个进程实现了mmap()系统调用主要负责 创建数据接收的缓存空间 管理数据接收缓存 b. 注传统的跨进程通信需拷贝数据2次但Binder机制只需1次主要是使用到了内存映射具体下面会详细说明
2.3 内存映射
内存映射 在 Linux操作系统中非常重要因为其涉及到高效的跨进程通信 文件操作
关联进程中的1个虚拟内存区域 1个磁盘上的对象使得二者存在映射关系
上述的映射过程 初始化该虚拟内存区域虚拟内存区域被初始化后就会在交换空间中换你来还去被映射的对象称为共享对象普通文件 / 匿名文件
2.3.1 作用
若存在上述映射关系则具备以下特征
在多个进程的虚拟内存区域 已和同1个共享对象 建立映射关系的前提下若 其中1个进程对该虚拟区域进行写操作那么对于 也把该共享对象映射到其自身虚拟内存区域的进程 也是可见的
示意图如下
假设进程1、2的虚拟内存区域同时映射到同1个共享对象当进程1对其虚拟内存区域进行写操作时也会映射到进程2中的虚拟内存区域 2.3.2 实现过程
内存映射的实现过程主要是通过Linux系统下的系统调用函数mmap该函数的作用 创建虚拟内存区域 与共享对象建立映射关系其函数原型、具体使用 内部流程 如下
/*** 函数原型*/
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);/*** 具体使用用户进程调用mmap* 下述代码即常见了一片大小 MAP_SIZE的接收缓存区 关联到共享对象中即建立映射*/mmap(NULL, MAP_SIZE, PROT_READ, MAP_PRIVATE, fd, 0);/*** 内部原理* 步骤1创建虚拟内存区域* 步骤2实现地址映射关系即进程的虚拟地址空间 - 共享对象* 注 * a. 此时该虚拟地址并没有任何数据关联到文件中仅仅只是建立映射关系* b. 当其中1个进程对虚拟内存写入数据时则真正实现了数据的可见*/2.3.3 特点
提高数据的读、写 传输的时间性能 减少了数据拷贝次数用户空间 内核空间的高效交互通过映射的区域 直接交互用内存读写 代替 I/O读写
提高内存利用率通过虚拟内存 共享对象
2.3.4 应用场景
在Linux系统下根据内存映射的本质原理 特点其应用场景在于
实现内存共享如 跨进程通信提高数据读 / 写效率 如 文件读 / 写操作
2.3.5 实例讲解
下面我将详细讲解 内存映射应用在跨进程通信 文件操作的实例
① 文件读 / 写操作
传统的Linux系统文件操作流程如下 使用了内存映射的 文件读 / 写 操作 从上面可看出使用了内存映射的文件读/写 操作方式效率更加高、性能最好
② 跨进程通信
传统的跨进程通信 使用了内存映射的 跨进程通信 从上面可看出使用了内存映射的跨进程通信 效率最高、性能最好
3. Binder 跨进程通信机制模型
3.1 模型原理图
Binder 跨进程通信机制 模型 基于 Client - Server 模式 3.2 模型组成角色说明 此处重点讲解 Binder驱动的作用 原理
简介 跨进程通信的核心原理 3.3 模型原理步骤说明 3.4 额外说明
说明1Client进程、Server进程 Service Manager 进程之间的交互 都必须通过Binder驱动使用 open 和 ioctl文件操作函数而非直接交互
原因
Client进程、Server进程 Service Manager进程属于进程空间的用户空间不可进行进程间交互Binder驱动 属于 进程空间的 内核空间可进行进程间 进程内交互
所以原理图可表示为以下
虚线表示并非直接交互 说明2 Binder驱动 Service Manager进程 属于 Android基础架构即系统已经实现好了而Client 进程 和 Server 进程 属于Android应用层需要开发者自己实现
所以在进行跨进程通信时开发者只需自定义Client Server 进程 并 显式使用上述3个步骤最终借助 Android的基本架构功能就可完成进程间通信 说明3Binder请求的线程管理
Server进程会创建很多线程来处理Binder请求Binder模型的线程管理 采用Binder驱动的线程池并由Binder驱动自身进行管理
而不是由Server进程来管理的
一个进程的Binder线程数默认最大是16超过的请求会被阻塞等待空闲的Binder线程。
所以在进程间通信时处理并发问题时如使用ContentProvider时它的CRUD创建、检索、更新和删除方法只能同时有16个线程同时工作
至此我相信大家对Binder 跨进程通信机制 模型 已经有了一个非常清晰的定性认识下面我将通过一个实例分析Binder跨进程通信机制 模型在 Android中的具体代码实现方式
即分析 上述步骤在Android中具体是用代码如何实现的
4. Binder机制 在Android中的具体实现原理
Binder机制在 Android中的实现主要依靠 Binder类其实现了IBinder 接口下面会详讲实例说明Client进程 需要调用 Server进程的加法函数将整数a和b相加
即
Client进程 需要传两个整数给 Server进程Server进程 需要把相加后的结果 返回给Client进程
具体步骤 下面我会根据Binder 跨进程通信机制 模型的步骤进行分析
步骤1注册服务
过程描述 Server进程 通过Binder驱动 向 Service Manager进程 注册服务代码实现 Server进程 创建 一个 Binder 对象
Binder 实体是 Server进程 在 Binder 驱动中的存在形式该对象保存 Server 和 ServiceManager 的信息保存在内核空间中Binder 驱动通过 内核空间的Binder 实体 找到用户空间的Server对象
代码分析 Binder binder new Stub();// 步骤1创建Binder对象 -分析1// 步骤2创建 IInterface 接口类 的匿名类// 创建前需要预先定义 继承了IInterface 接口的接口 --分析3IInterface plus new IPlus(){// 确定Client进程需要调用的方法public int add(int a,int b) {return ab;}// 实现IInterface接口中唯一的方法public IBinder asBinder{ return null ;}
};// 步骤3binder.attachInterface(plusadd two int);// 1. 将add two intplus作为key,value对存入到Binder对象中的一个MapString,IInterface对象中// 2. 之后Binder对象 可根据add two int通过queryLocalIInterface获得对应IInterface对象即plus的引用可依靠该引用完成对请求方法的调用// 分析完毕跳出-- 分析1Stub类 --public class Stub extends Binder {// 继承自Binder类 -分析2// 复写onTransactOverrideboolean onTransact(int code, Parcel data, Parcel reply, int flags){// 具体逻辑等到步骤3再具体讲解此处先跳过switch (code) { case Stub.add { data.enforceInterface(add two int); int arg0 data.readInt();int arg1 data.readInt();int result this.queryLocalIInterface(add two int) .add( arg0, arg1); reply.writeInt(result); return true; }} return super.onTransact(code, data, reply, flags); }
// 回到上面的步骤1继续看步骤2-- 分析2Binder 类 --public class Binder implement IBinder{// Binder机制在Android中的实现主要依靠的是Binder类其实现了IBinder接口// IBinder接口定义了远程操作对象的基本接口代表了一种跨进程传输的能力// 系统会为每个实现了IBinder接口的对象提供跨进程传输能力// 即Binder类对象具备了跨进程传输的能力void attachInterface(IInterface plus, String descriptor)// 作用// 1. 将descriptorplus作为key,value对存入到Binder对象中的一个MapString,IInterface对象中// 2. 之后Binder对象 可根据descriptor通过queryLocalIInterface获得对应IInterface对象即plus的引用可依靠该引用完成对请求方法的调用IInterface queryLocalInterface(Stringdescriptor) // 作用根据 参数 descriptor 查找相应的IInterface对象即plus引用boolean onTransact(int code, Parcel data, Parcel reply, int flags)// 定义继承自IBinder接口的// 作用执行Client进程所请求的目标方法子类需要复写// 参数说明// codeClient进程请求方法标识符。即Server进程根据该标识确定所请求的目标方法// data目标方法的参数。Client进程传进来的此处就是整数a和b// reply目标方法执行后的结果返回给Client进程// 注运行在Server进程的Binder线程池中当Client进程发起远程请求时远程请求会要求系统底层执行回调该方法final class BinderProxy implements IBinder {// 即Server进程创建的Binder对象的代理对象类// 该类属于Binder的内部类}// 回到分析1原处
}-- 分析3IInterface接口实现类 --public interface IPlus extends IInterface {// 继承自IInterface接口-分析4// 定义需要实现的接口方法即Client进程需要调用的方法public int add(int a,int b);
// 返回步骤2
}-- 分析4IInterface接口类 --
// 进程间通信定义的通用接口
// 通过定义接口然后再服务端实现接口、客户端调用接口就可实现跨进程通信。
public interface IInterface
{// 只有一个方法返回当前接口关联的 Binder 对象。public IBinder asBinder();
}// 回到分析3原处注册服务后Binder驱动持有 Server进程创建的Binder实体
步骤2获取服务
Client进程 使用 某个 service前此处是 相加函数须 通过Binder驱动 向 ServiceManager进程 获取相应的Service信息具体代码实现过程如下 此时Client进程与 Server进程已经建立了连接
步骤3使用服务
Client进程 根据获取到的 Service信息Binder代理对象通过Binder驱动 建立与 该Service所在Server进程通信的链路并开始使用服务
过程描述 Client进程 将参数整数a和b发送到Server进程Server进程 根据Client进程要求调用 目标方法即加法函数Server进程 将目标方法的结果即加法后的结果返回给Client进程
代码实现过程
步骤1 Client进程 将参数整数a和b发送到Server进程
// 1. Client进程 将需要传送的数据写入到Parcel对象中
// data 数据 目标方法的参数Client进程传进来的此处就是整数a和b IInterface接口对象的标识符descriptorandroid.os.Parcel data android.os.Parcel.obtain();data.writeInt(a); data.writeInt(b); data.writeInterfaceToken(add two int);// 方法对象标识符让Server进程在Binder对象中根据add two int通过queryLocalIInterface查找相应的IInterface对象即Server创建的plusClient进程需要调用的相加方法就在该对象中android.os.Parcel reply android.os.Parcel.obtain();// reply目标方法执行后的结果此处是相加后的结果// 2. 通过 调用代理对象的transact 将 上述数据发送到Binder驱动binderproxy.transact(Stub.add, data, reply, 0)// 参数说明// 1. Stub.add目标方法的标识符Client进程 和 Server进程 自身约定可为任意// 2. data 上述的Parcel对象// 3. reply返回结果// 0可不管// 注在发送数据后Client进程的该线程会暂时被挂起
// 所以若Server进程执行的耗时操作请不要使用主线程以防止ANR// 3. Binder驱动根据 代理对象 找到对应的真身Binder对象所在的Server 进程系统自动执行
// 4. Binder驱动把 数据 发送到Server 进程中并通知Server 进程执行解包系统自动执行
步骤2Server进程根据Client进要求 调用 目标方法即加法函数
// 1. 收到Binder驱动通知后Server 进程通过回调Binder对象onTransact进行数据解包 调用目标方法public class Stub extends Binder {// 复写onTransactOverrideboolean onTransact(int code, Parcel data, Parcel reply, int flags){// code即在transact中约定的目标方法的标识符switch (code) { case Stub.add { // a. 解包Parcel中的数据data.enforceInterface(add two int); // a1. 解析目标方法对象的标识符int arg0 data.readInt();int arg1 data.readInt();// a2. 获得目标方法的参数// b. 根据add two int通过queryLocalIInterface获取相应的IInterface对象即Server创建的plus的引用通过该对象引用调用方法int result this.queryLocalIInterface(add two int) .add( arg0, arg1); // c. 将计算结果写入到replyreply.writeInt(result); return true; }} return super.onTransact(code, data, reply, flags); // 2. 将结算结果返回 到Binder驱动
步骤3Server进程 将目标方法的结果即加法后的结果返回给Client进程 // 1. Binder驱动根据 代理对象 沿原路 将结果返回 并通知Client进程获取返回结果// 2. 通过代理对象 接收结果之前被挂起的线程被唤醒binderproxy.transact(Stub.ADD, data, reply, 0)reply.readException();result reply.readInt()}
}
总结 下面我用一个原理图 流程图来总结步骤3的内容 5. 优点
对比 Linux Android基于Linux上的其他进程通信方式管道、消息队列、共享内存、 信号量、SocketBinder 机制的优点有 特别地对于从模型结构组成的Binder驱动来说 整个Binder模型的原理步骤 源码分析 该博主相关文章写的都很好非常推荐阅读原文链接
Android跨进程通信图文详解 Binder机制 原理_android binder机制_Carson带你学Android的博客-CSDN博客
操作系统图文详解 内存映射 - 简书