阅读 677

Binder机制

简介

Binder是Android下基于C/S架构的IPC机制,用来实现不用进程间通信。IPC是Inter-Process-Communication的缩写,意思是进程间通信或者跨进程通信。Binder属于一个驱动,工作在linux层,运行在kernel。
Android 进程间通信的方式有很多种,比如 Messenger、文件(SharePreference)、AIDL、Socket 和 Content Provider 等,它们当中 Messenge、AIDL 和 Content Provider 的底层都是依赖于 Binder 机制去实现的。 因为Android系统是基于Linux内核的,所以了解Binder机制需要了解一些基本linux机制。

进程隔离

进程隔离技术是为了避免进程A写入进程B的情况发生。 进程的隔离实现,使用了虚拟地址空间。进程A的虚拟地址和进程B的虚拟地址不同,这样就防止进程A将数据信息写入进程B。"这段引用自维基百科,正是由于进程隔离的存在,所以需要一种机制才能完成一个进程与另外一个进程的通信。

用户空间/内核空间

由于 Linux 采用了虚拟地址空间技术,操作系统在逻辑上将虚拟内存分为用户空间(User Space)和内核空间(Kernel Space)普通应用程序运行在用户空间,系统内核运行在内核空间,为了控制应用程序的访问范围、保证系统安全,用户空间只能通过系统调用的方式去访问内核空间。当进程执行系统调用而陷入内核代码的时候,该进程则进入了内核态,相比之下,进程在用户空间执行自己的代码的时候,则是处于用户态

内核模块/驱动

传统的Linux通信机制,比如Socket,管道等都有内核支持,Binder不属于Linux内核的一部分,它是通过Linux的动态可加载内核模块(Loadable Kernel Module)机制来实现的。模块是具有独立功能的程序,它可以被单独编译,但不能独立运行。它在运行时被链接到内核作为内核的一部分在内核空间运行。
驱动就是操作硬件的接口,Binder驱动就是这样一个运行在内核空间的,负责各个用户进程通信的内核模块。

Linux IPC 原理

Linux 采用了虚拟地址空间技术.操作系统在逻辑上将虚拟内存分为用户空间(User Space)和内核空间(Kernel Space),普通应用程序运行在用户空间,系统内核运行在内核空间,为了控制应用程序的访问范围、保证系统安全,用户空间只能通过系统调用的方式去访问内核空间。 进程 A 和进程 B 的虚拟地址.些情况下有些进程难免会需要跟其他进程进行交互,这个交互过程就叫 IPC(Inter-Process Communication,进程间通信)。IPC 的实质就是数据的交互,
Linux 本身已经具有了许多的 IPC 机制,如管道(Pipe)、信号(Signal)和跟踪(Trace)、插口(Socket)、消息队列(Message)、共享内存(Share Memory)和信号量(Semaphore) 详细linux中的ipc 查看 blog.csdn.net/a987073381/…
为什么有了linux IPC机制还需要Android IPC(Binder)机制呢?

性能

  • Socket :传输效率低, 开销大, 主要用在跨网络的进程间通信和本机上进程间的低速通信.但是接口通用. 数据 copy 方式和 消息队列/管道 相同.
  • 消息队列/管道: 控制复杂, 难以使用. 数据 copy 0 次
  • Binder :借用内存映射, 在内核空间和接收方用户空间的数据缓存区做了一层内存映射. 意思就是说,在发送方将数据 copy 到内核空间的时候, 内核空间的这部分地址同时也会被映射到接收方的内存缓存中, 这样就减少了一次数据的 copy.
  • 内存共享:实现方式复杂, 没有客户端与服务端之别, 需要充分考虑到访问临街资源的并发同步问题,否则可能会出现死锁等问题.

易用性

  • 内存共享:实现方式复杂, 没有客户端与服务端之别, 需要充分考虑到访问临街资源的并发同步问题,否则可能会出现死锁等问题.
  • Binder:基于 C/S 架构,客户端有什么需求就丢给服务端去完成,架构清晰,职责明确又相互独立.

安全性

  • 传统 IPC:传统的 IPC 没有任何安全措施, 完全依赖商城协议来确保.
  • Binder Android 为每个安装好的 APP 都分配了自己的 UID,故而进程的 UID 是鉴别进程身份的重要标识. 可靠的身份标识只有由 IPC 机制在内核中添加,才可靠. Binder 既提供了实名 Binder, 还支持匿名 Binder. 安全性高.

Android 系统来说传统的进程间通信方式 copy 次数多,耗费时间. 接收方不知道需要分配多大的内存接收数据, 或者是需要提前通知接收方而耗费时间. 内存共享又太难以控制,复杂度较高.所以建立倆一套Android 的IPC机制

内存映射

mmap() 是操作系统中一种内存映射的方法. 简单的说就是将用户空间的一块内存区域映射到内核空间.映射关系建立后, 用户对这块内存区域的修改可以直接反应到内核空间.反之,内核空间对这段区域的修改也能直接反应到用户空间.

Linux PC 通信的过程如下

  1. 数据发送方进程将数据放在内存缓存区,通过系统调用陷入内核态
  2. 内核程序在内核空间开辟一块内核缓存区,通过 copy_from_user 函数将数据从数据发送方用户空间的内存缓存区拷贝到内核空间的内核缓存区中。
  3. 数据接收方进程在自己的用户空间开辟一块内存缓存区
  4. 内核程序将内核缓存区中通过 copy_to_user 函数将数据拷贝到数据接收方进程的内存缓存区

如上图所示会有两个问题:

  • 通过函数copy_from_user从进程A的内存缓存区放到内核缓存区需要一次copy,在从内核缓存区 通过函数copy_to_user copy到进程B的内存缓存区 比较耗费性能
  • 接收方进程事先不知道需要开辟多大的内存用于存放数据,因此需要开辟尽可能大的空间或者事先调用 API 来解决这个问题,

Binder IPC 原理

从实现上来说可分为Binder驱动、ServiceManager、Server、Client四个组成部分。Android Binder是借助 mmap()来实现一次copy的。

其中,Client、Server 和 ServiceManager 运行在用户空间,Binder Driver 运行在内核空间,Client 和 Server 需由用户自己实现,ServiceManager 和 Binder Driver 则由系统提供。Binder IPC 通信过程通常:

  1. 首先 Binder 驱动在内核空间创建一个数据接收缓存区
  2. 接着在内核空间开辟一块内核缓存区.
  3. 建立内核缓存区 和 内核中数据接收缓存区 之间的映射关系.
  4. 建立内核中数据接收缓存区 与 数据接收进程用户空间 的地址的映射关系
  5. 发送方进程通过系统调用 copy_from_user() 将数据 copy 到内核中的内核缓存区, 由于内核缓存区 与 内核数据接收缓存区 存在映射关系, 而内核数据接收缓存区 又与 数据接收进程用户空间 存在映射关系, 所以相当于 内核缓存区 与 数据接收进程用户空间存在映射关系. 因此也就相当于把数据发送到了数据接收进程的用户空间.

Binder 模型原理图

在Android系统的Binder机制中,由一系统组件组成,分别是Client、Server、Service Manager和Binder驱动程序(其中Client、Server和Service Manager运行在用户空间,Binder驱动程序运行内核空间)。Binder就是一种把这四个组件粘合在一起的粘结剂了,其中,核心组件便是Binder驱动程序了,Service Manager提供了辅助管理的功能,Client和Server正是在Binder驱动和Service Manager提供的基础设施上,进行Client-Server之间的通信。
Android 具体使用AIDL请自行查阅相关文章

文章分类
Android