Android面试题讲解-为什么要采用Binder作为IPC机制

要知道,Android系统进程间通信(IPC)方式有很多种,比如:比如 Messenger、文件(SharePreference)、AIDL、Socket 和 Content Provider 等。而Android的内核也是基于Linux内核,并且Linux已经拥有管道,system V IPC,socket等IPC手段。为何不直接采用Linux现有的进程IPC方案却使用倚赖Binder来实现进程间通信呢?对此,小编带大家从以下几点分析。

一,什么是IPC机制,IPC的种类有哪些?

IPC的含义为进程间通信或跨进程通信,是指在两个进程之间进行数据交换。进程一般是指一个执行单位,通俗一点的说法就是一个应用程序。进程是一个独立的资源分配单元,一般情况下,进程之间是没有关联的,但很多时候,系统需要多个相关的进程来共同完成一项任务,就需要进程之间能够相互通信,才能共享资源和信息。所以就需要进程间的通信机制(IPC)。

IPC机制主要有以下四种:

  • 采用命名管道(name pipe)
  • 消息队列(message queue)
  • 信号(signal)
  • 内存共享(share memory)

二,Linux IPC原理

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

由于两个进程间的虚拟地址不同,因此它们不能察觉到对方的存在,都认为自己可以独享整个系统的资源,当然也不能让它们之间交互。但在特殊情况下,就很难避免一些进程与其他进程进行交互,这个过程就叫 IPC(Inter-Process Communication,进程间通信)。IPC的本质就是数据的交互,所以我们在这个时候就需要将进行在IPC 过程中的通信调用方和被调用放分别称为数据发送方和数据接收方,IPC 通信的过程如下:

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

Android面试题讲解-为什么要采用Binder作为IPC机制_第1张图片

按照图中流程,进行一次IPC就完成了,但这种传统的IPC机制会有两个问题,分别是:

  • 性能比较低:整个过程数据的传递需要经历发送方内存缓存区——内核缓存区——接收方内存缓存区的过程。
  • 接收方进程事先不知道需要开辟多大的内存用于存放数据,因此需要开辟尽可能大的空间或者事先调用 API 来解决这个问题,这两种方式不是浪费空间就是浪费时间。

三,Binder IPC 原理

为了弥补传统Linux IPC机制的不足,Android系统引入了Binder机制,BInder能让不同的进程之间相互通信。在上节Linux IPC 原理中就有讲到过,进程间的相互通信需要Linux内核的支持,而Binder不属于内核的一部分,但得益于 Linux 的 LKM(Loadable Kernel Module) 机制:

binder是具有独立功能的程序,它可以被单独编译,但不能独立运行。它在运行时被链接到内核作为内核的一部分在内核空间运行

因为Binder IPC可以在内核空间运行,所以也被称为Binder驱动。对比上一小节的内容,传统Linux IPC机制需要经历两次数据拷贝,而Binder可以借助Linux的另一个特效,只需要拷贝一次数据就可以实现IPC过程,这种就叫做内存映射:

内存映射就是指将用户空间的一块内存区域映射到内核控制,需要通过mmap实现,mmap是在操作系统中实现内存映射的一种方法,映射关系建立完成后,开发者对这块内存区域的修改将直接同步到内核空间;当然,如果对内核空间这块区域修改也会直接同步到用户空间。

内存映射能减少数据拷贝次数,实现用户空间和内核空间的高效互动。两个空间各自的修改能直接反映在映射的内存区域,从而被对方空间及时感知。也正因为如此,内存映射能够提供对进程间通信的支持。

Binder IPC 通信过程如下:

  • Binder 驱动在内核空间创建一个 数据接收缓存区
  • 然后在内核空间开辟一块 内存缓存区 并与数据接收缓存区建立映射关系,同时,建立数据接收缓存区 与 数据接收方的内存缓存区 的映射关系
  • 数据发送方通过系统调用 copy_from_user函数将数据从内存缓存区拷贝到内核缓存区,由于内核缓存区通过数据接收缓存区跟数据接收方的内存缓存区存在间接的映射关系,相当于将数据直接拷贝到了接收方的用户空间,这样便完成了一次PC 的过程。
    Android面试题讲解-为什么要采用Binder作为IPC机制_第2张图片
    总结

在Android中为什么要采用Binder作为IPC机制,而不是采用现有的LInux IPC呢?因为Linux 在进行IPC通信过程时需要经历两次数据拷贝,而且需要提前开辟较大的内存空间来存放数据,因此需要花费很长的时间成本。BInder刚好就弥补了这一缺陷;所以,选择Binder作为IPC机制,能在工作上节省很多时间成本。

本文在写作过程中参考《Android Framework内核解析》这份学习文档,里面讲到了Binder,Handler消息机制,Dalvik vm 进程系统等知识点,也包含了一些面试题,分享在下面。
Android面试题讲解-为什么要采用Binder作为IPC机制_第3张图片

《Android Framework内核解析》
【​docs.qq.com/doc/DWFdlc2JocEtNbEJ1】全部内容分享

你可能感兴趣的:(android,binder,linux)