Android Binder驱动的工作机制之要旨

最近,看了不少Android内核分析的书籍、文章及Android源程序。感觉自己对Android Binder的工作机制算是有了个彻底的理解。


但是,自己是花了很多时间和精力之后才达到这一点的。对于大多数人来说,恐怕不会象我这样愿意花这么大的代价就为了弄明白这一点东西。所以,我想尽可能简要的介绍一下Android Binder驱动的工作机制原理,以使大家不必花太多时间也能弄明白其要旨。


一、我们先介绍一下Binder Driver所要解决的问题。

       Binder driver所要解决的是运行在同一个Android操作系统中的不同进程之间的小规模数据的传递问题。

       注意,对于不同进程之间的大规模数据的传递问题,Android是用Android Shared Memory Driver来解决的。Binder Driver是针对小规模的数据传递的(比如几十字节到几十KB的数据)。

       Android Driver是整个Android Binder系统的内核部分。Android Binder系统的目标是提供一个运行在同一个Android操作系统中的不同进程间通信的面向对象的API,类似于Microsoft DCOM或者CORBA。为了提供这样的面向对象的API, Android需要一种高效的进程间通信机制,这就是Android driver存在的目的。


二、那么,为什么不直接用Linux的共享内存机制来在进程间传递数据呢?

        这是因为,除了传递数据之外,Android还需要这个Driver支持以下特性。

       1. 安全机制:只有特定的用户和进程才能访问这块数据。Linux共享内存不支持这样的机制。

       2. 引用计数:只有Client进程不再需要了,其对应的Server进程才能释放相应的内存。Linux共享内存也不支持这样的机制。

       3. 另外,Android Binder driver还支持夸进程的描述符传递。这样,一个进程可以直接读另一个进程打开的文件,而不需要将文件内容读到内存后再复制给另一个进程。


三、Linux进程的虚拟内存空间

       下面以x86 CPU的Linux实现为例,回顾一下Linux进程的虚拟内存空间的相关知识。

        1. 每个进程有4G的虚拟内存空间

        2.这4G空间分为两部分。0~3G为用户态空间(User Space),3~4G为内核态空间(Kernel Space)。

        3.对于0~3G的用户态空间,对于不同的进程,Linux会将其映射到不同的物理内存。比如,进程A的虚拟地址0x01234567所指向的物理地址与进程B的虚拟地址0x01234567所指向的物理地址是不同的。这就是所谓的进程隔离。

        4.对于3~4G的内核态空间,对于所有的进程,Linux会将其映射到相同的物理内存。换句话说,进程A的虚拟地址0xC1234567与进程B的虚拟地址0xC1234567指向的是同一个物理地址。这部分虚拟内存空间,用户态的进程是不能访问的,只有切换到内核态的进程才能访问一个进程的3~4G的内核态空间。



四、将数据从进程A传递到进程B的确切含义

       所谓将数据从进程A传递到进程B,就是将进程A的某块用户空间(0~3G)的内容复制到进程B的某块用户空间(0~3G)的内存中。

      

        因此,为了将数据从一个进程A复制到另一个进程B,我们需要:

        1. 切换到内核态。因为只有内核态才能访问所有进程的用户态空间。

        2. 将数据从进程A的用户态空间读出。

        3. 在进程B的用户态空间中找一块内存空间,为其分配物理内存,然后将数据复制到该物理内存处。

        4. 然后,进程B就可以从其用户空间读到数据了。


五、Binder Driver是如何在进程间传递数据的

       其实,Binder driver要做的事情就是上面我们所列出的那几个步骤。

       不过,对于每个进程,Binder driver会在进程打开binder driver后,通过ioctl系统调用为每个进程预先找一块用户态和内核态的内存空间,做为Binder buffer使用。

       请注意,对于一个进程而言,其Binder buffer在用户态和内核态的内存被映射到了同样的物理内存地址。


       下面我们看看利用Binder进行通信的两个进程之间是如何传递数据的:

       1. Client进程有一块内存内容需要传递给Server进程

       2. 切换到内核态

       3. Binder driver读Client进程的用户态空间(0~3G)的这块内存内容

       4. Binder driver将读出的内容复制到Server进程的Binder buffer中

       5. 然后,当Server进程执行时,就能够在其用户态空间(0~3G)读传过来的内容了。因为Binder Buffer也被映射到了Server进程的用户态空间。

       6. 当Server进程处理完读出的消息后,然后需要将处理的结果存放在一块用户态空间的内存中,希望将其返回给Client进程

       7. 切换到内核态

       8. Binder driver读Server进程的用户态空间(0~3G)的处理结果

       4. Binder driver将读出的内容复制到Client进程的Binder buffer中

       5. 然后,当Client进程执行时,就能够在其用户态空间(0~3G)读传过来的内容了。因为Binder Buffer也被映射到了Client进程的用户态空间。


       这就是Binder driver如何实现进程间通信的。

       至于其中的细节,比如安全机制的实现,就不多说了。感兴趣的请参考老罗的鸿篇巨著《Android系统源代码情景分析》,里边有两百余页的篇幅讲Binder系统。不过,要看懂这些内容,需要有较深的Linux Kernel知识。

     

      


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值