Android系统 Binder机制浅析(一)

Binder是Android系统中最重要的特征之一,它是系统间各个组件的桥梁,Android系统的开放式设计也很大程度上得益于这种极其方便的跨进程通信机制。理解Binder对于理解整个Android系统有着非常重要的作用,Android系统的四大组件,AMS,PMS等系统服务无一不与Binder 挂钩;要深入Android,Binder是必须迈出的一步。

问题: 
  1. 为什么需要跨进程通信(IPC)?
  2. 怎么做到跨进程通信? 
  3. 为什么使用Binder?
为了搞清这三个问题,有必要了解以下相关知识。

(一)进程隔离

进程隔离是为了保护操作系统中进程互不干扰而设计的一组不同硬件和软件的技术。这个技术是为了防止进程A写入了进程B的情况发生。进程隔离的实现,使用了虚拟地址空间,进程A的虚拟地址和进程B的虚拟地址不相同;这样就防止进程A将数据写入了进程B中。

操作系统的不同进程之间,数据不共享;对于每个进程而言,它都天真的以为自己独享着整个系统,完全不知道其他进程的存在。

因此,如果一个进程需要与另一个进程进行通信,就需要有某种系统机制才能完成。

(二)用户空间/内核空间

Linux Kernel是操作系统的核心,独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限。

对于Kernel这么一个高安全级别的东西,显然是不容许其它的应用程序随便调用或访问的,所以需要对Kernel提供一定的保护机制,这个保护机制用来告诉那些应用程序,你只可以访问某些许可的资源,不许可的资源是拒绝被访问的,于是就把Kernel和上层的应用程序抽像的隔离开,分别称之为Kernel SpaceUser Space

(三)系统调用/内核态/用户态

虽然从逻辑上抽离出用户空间和内核空间;但是不可避免的的是,总有那么一些用户空间需要访问内核的资源;比如应用程序访问文件,网络是很常见的事情,怎么办呢?

Kernel space can be accessed by user processes only through the use of system calls.

用户空间访问内核空间的唯一方式就是系统调用

通过这个统一入口接口,所有的资源访问都是在内核的控制下执行,以免导致对用户程序对系统资源的越权访问,从而保障了系统的安全和稳定。

当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态(或简称为内核态)。此时处理器处于特权级最高的(0级)内核代码中执行。当进程在执行用户自己的代码时,则称其处于用户运行态(用户态)。即此时处理器在特权级最低的(3级)用户代码中运行。处理器在特权等级高的时候才能执行那些特权CPU指令。

(四)内核模块/驱动

       通过系统调用,用户空间可以访问内核空间,那么如果一个用户空间想与另外一个用户空间进行通信怎么办呢?很自然想到的是让操作系统内核添加支持;传统的Linux通信机制,比如Socket,管道等都是内核支持的;但是Binder并不是Linux内核的一部分,它是怎么做到访问内核空间的呢?Linux的动态可加载内核模块(Loadable Kernel Module,LKM)机制解决了这个问题;模块是具有独立功能的程序,它可以被单独编译,但不能独立运行,它在运行时被链接到内核作为内核的一部分在内核空间运行。这样,Android系统可以通过添加一个内核模块运行在内核空间,用户进程之间的通过这个模块作为桥梁,就可以完成通信了。

在Android系统中,这个运行在内核空间的,负责各个用户进程通过Binder通信的内核模块叫做Binder驱动;

驱动就是操作硬件的接口,为了支持Binder通信过程,Binder使用了一种“硬件”,因此这个模块被称之为驱动。
(驱动程序一般指的是设备驱动程序(Device Driver),是一种可以使计算机和设备通信的特殊程序。相当于硬件的接口,操作系统只有通过这个接口,才能控制硬件设备的工作)

(五)为什么使用Binder?

Android使用的Linux内核拥有着非常多的跨进程通信机制,比如管道,System V,Socket等;

为什么还需要单独搞一个Binder出来呢?主要有两点,性能和安全

在移动设备上,广泛地使用跨进程通信肯定对通信机制本身提出了严格的要求;Binder相对于传统的Socket方式,更加高效;另外,传统的进程通信方式对于通信双方的身份并没有做出严格的验证,只有在上层协议上进行架设;比如Socket通信ip地址是客户端手动填入的,都可以进行伪造;而Binder机制从协议本身就支持对通信双方做身份校检,因而大大提升了安全性。这个也是Android权限模型的基础。

Android系统Binder机制中的四个组件Client、Server、Service Manager和Binder驱动程序的关系如下图所示:

Android系统 Binder机制浅析(一)

        1. Client、Server和Service Manager实现在用户空间中,Binder驱动程序实现在内核空间中

        2. Binder驱动程序和Service Manager在Android平台中已经实现,开发者只需要在用户空间实现自己的Client和Server

        3. Binder驱动程序提供设备文件/dev/binder与用户空间交互,Client、Server和Service Manager通过open和ioctl文件操作函数与Binder驱动程序进行通信

        4. Client和Server之间的进程间通信通过Binder驱动程序间接实现
        5. Service Manager是一个守护进程,用来管理Server,并向Client提供查询Server接口的能力

(六)Binder Driver

       进程之间通信的数据都会经过运行在“内核空间”里面的驱动,驱动在数据流过的时候做了一点手脚,它并不会给Client进程返回一个真正的object对象,而是返回一个看起来跟object一模一样的代理对象objectProxy;这个代理对象objectProxy也有一个add方法,但是这个add方法没有server进程里面的object对象的add方法对的能力,代理对象objectProxy的add方法只是一个傀儡,它唯一的作用就是把参数包装然后传给驱动。
       Binder 驱动收到这个消息之后,发现是objectProxy.于是Binder 驱动通知server进程:"调用你的object对象的add方法,把结果返回给我"。Server收到这个消息,照做之后将结果返回给驱动,驱动然后把这个结果返回给Client进程,这样就完成了一次进程之间的通信。