(1)Framework框架 --- 基础(进程与Binder)

来源:互联网 发布:不起眼的赚钱行业 知乎 编辑:程序博客网 时间:2024/06/09 17:27
    

学习Android框架(Framework)的目的?

         我们可以列出一堆理由:

                既然期望能够在Android舞台上跳出优美的舞蹈,那么我们就应该知道舞台的大致模样。

                可以让软件设计的层次结构更加合理,让软件开发与实现更加得心应手。

                可以作为解决许许多多问题的通用参考工具。

                …

                但我更加相信:

                它代表了一种习惯,更体现了一种文化。在这种文化氛围中徜徉久了,潜移默化中,你就成为它的一个部分了。你会逐渐发现,许多乍看起来非常别扭的东西,却似 

                成相识。无论是Android框架, 还是Linux内核,抑或其它,都传承着同样的文化…

Android框架的要点?

               了解处于核心地位或具有特殊作用的模块或子系统。例如任务子系统(Activity & Activity Manager), 显示子系统 (View, Window Manager & SurfaceFlinger) 等。

                就一个特定子系统而言,可以了解它的基础设施,核心数据结构或对象。它们是较为成熟的通用方案,较少受版本更新的影响。

                可从一个用户的角度开始,分析特定进程使用核心子系统的状况,确认子系统实现其功能的步骤及方法。

                Android的各个子系统,其实是按照相同规则或习惯搭建起来的。

Android框架与Linux进程

                虽然,Android框架努力消除进程间的界限,但我们在源码分析中,不能无视它们的存在,它们是Linux操作系统控制的焦点。无论是Android,还是Ubuntu,进程的调度,资源分配,以及中断响应等等操作系统管理的核心,都是围绕着进程展开的。

                进程,可以作为学习Android框架的切入点。

                进程的要点罗列如下:

                                (a) 程序,共享库与进程

                                                图1: 一款Android手机的进程列表

                                                 

                                                图2: Linux进程的内存映像

                                               

                                (b) 进程与线程

                                (c) 内存映像

                                (c) 用户空间与内核空间

                                (d) 线程间同步机制

                                (e) 进程间通讯机制(IPC)

这些要点,我们迟早都会遇到。可以预料的是,它们还将继续存在下去。只要你愿意了解,它们就会成为我们手中的利器。在这个世界上,已经存在很久却仍然有效的利器,其实没有多少。

我们经常使用的是”进程间通讯机制” 来解剖Android框架。在计算机的世界里(至少在Linux内核的追求目标中),”进程”生来应该是平等的,没有什么客户进程,服务进程之分。

如果没有把许多应用程序都需要实现的机能,都交由一个特定应用程序来实现,从而以一个特定”服务”的形式呈现给大家,进程彼此之间无需知道对方的存在。就像你现在,完全不用考虑索马里的居民们每天都在干嘛。一个进程对另一个进程而言,似乎是生活在另一个星球一样。

但当一个进程仰仗另外一个进程,也就是”服务”,完成指定的任务时,情况就发生了变化。进程间的壁垒依然存在,这些壁垒仍然是现行体制下,保护大多数居民不受影响的最好手段。新的需求往往会酝酿出新的解决手段。

Linux常见的进程间通讯(IPC)手段都有哪些?

 (a) 管道 (PIPE /FIFO)。

 (b) 共享内存(Shared Memory)。

 (c) 信号 (Signal)。

 (d) 信号量(Semaphore)。

 (e) 消息队列(Message)

 (f)  套接口(Socket)       

图3: Linux进程进程间通讯

这些手段与进程线程等概念类似,也已经存在了好几十年了。它们都依赖Linux内核的参与,来建立进程间通讯的通道。Google在设计Android框架,整合各个子系统时,显然对这些老古董都看不上眼,他们选择了新鲜事物---Binder. Binder的高效安全或许很难说,但使用起来确实很简便,”面向对象”的设计使用理念也符合时代的潮流。              

Binder机制的要点

图4: Binder的组成与使用步骤

      (I) Binder的组成

           (1) Binder驱动                                      ---           内核的参与是所有IPC机制的基础

           (2) Binder Service管理器                 ---           中介机构,同时是一个Binder服务器

           (3) Binder服务端                                 ---           提供特定服务

           (4) Binder客户端                                  ---          服务的使用者

      (II) Binder通讯的建立步骤 ,参看图(4)。

           (1) Service管理器自身的注册。Service管理器在系统中只有一个,所以我们

  使用Binder时,不再需要注册我们自己的Service管理器。Service管理者

   需要通知Binder驱动,中介机构已经准备好了,所有其它的Service及以

   及客户都可以使用它的管理或咨询服务了。

           (2) 特定服务(Service)向中介机构,Service管理器,以系统中唯一的名称注册

  自己。

           (3) Client向管理器查询特定服务 。客户可以使用服务的唯一的名字找到特定

  服务。

           (4) Client享用特定服务

      (III) 特点

           (1) 本地代理与远端服务

   使用Binder进行通信的两端,往往存在于不同的两个进程里。在使用中,

   我们会发现,有专门的Binder线程用于Binder通讯,Binder的底层库已

   经打理好了这一切,让我们致力于特定的请求与相应,不用考虑通讯是如

   何实现的。 但在分析Android源码时,我们需要知道,Binder客户端有一

   个本地代理结构(bpXXXXX),而服务端有一个本地服务结构(bnXXXX)用于通

   讯。P 代表 Proxy  N代表着 Native.

           (2) Binder对象的引用可以跨进程的传递

                   这一点很有意思。以往的IPC通讯都只局限于两两之间。现在Binder可以

   做到,A提供服务,B得到服务使用许可证(即上述的服务代理),B还可

   以把它传递给第三者C,让C也使用A的服务。

熟悉Binder的使用对我们了解Android框架影响很大,所以,我们再仔细看看下图。

如果大家对Binder的实现感兴趣,可以看看它的协议。但大家完成一个目标前,

最好不要分散自己的注意力,这点要切记。

Binder的使用与示例

Binder的使用步骤如下图(5)

(1)客户端使用服务前,首先向服务管理器(sm)查询特定服务(getService)

(2)客户端代理(bp),通常实现特定接口,以供客户端使用。

(3)客户端调用接口的特定函数,如functionN时,客户端代理赋予该函数特定的编号 N,并将该编号及参数打成Parcel包(可以认为是一个二进制序列),代理将其发送给服务端。

(4)客户端代理将等待返回的结果。

(5)Binder服务端(bn)接收到Parcel包后,将按照函数序号N,转化为调用函数functionN,并传入从Parcel包提取的参数。

(6)Binder服务处理完毕请求后,将结果也打成Parcel包,并由bn端传送回客户端代理。

(7)客户端继续运行。

图5: Binder的使用

 

使用Binder的一个简单的示例如下图(6)

图(6) 使用Binder的服务与客户应用程序

示例要点:

(1)服务程序使用manifest.xml文件标示自己的服务

(2)服务程序创建服务实例,为客户端提供服务.

(3)客户端通过“服务的名字”来获得特定的服务

(4)获得服务后,对客户而言,该服务的使用与本地函数的使用没有差别。

在解析Android框架源码时,我们遇到的Binder的使用形式,往往是下面这个样子,参看图7,该示例取自Window Manager。

图(7) Framework中使用Binder

示例要点:

(1) 特定的服务,如”window”服务,都派生并实现一个特定公共接口。

(2) 客户端的程序,依据”服务的名字”,查询服务管理器 (ServiceManager),获得服

     务。

     客户端,像使用自身的函数一样使用,(远端)服务的公共接口函数.

(3) 有些服务的公共接口函数,如上图的OpenSession,可以把服务端的带有匿名服

    务接口的结构,其实是另外一个Binder对象的代理,提供给客户端。客户端可

    以与这个匿名对象通讯了。

    这种使用模式类似于TCP Socket。 客户端都知道公共Socket端口,向服务端发

    出连接请求后,它就通过Bind告诉用户,”我只是负责接待登记的,具体事宜的

    办事员,我告诉你,以后你就找他吧”. 

    这里的概念是等同的。这样做,不仅能够实现对客户的一对一服务,还可以做到

    对客户的统一管理。

后记

如果把上述例子进一步扩展,我们可以看到下述情形。

                客户端通过查询”服务端”的名字获得服务。  

                客户端调用服务的接口,得到服务器内部维护的另外一个匿名服务。

                由于这些服务什么时候完成,往往不确定。考虑到效率,响应往往是异步的。

                客户端通常也要维护一个Binder接口,其实是客户端提供的匿名服务,从而让服务

端使用该接口,把请求的结果返回给客户端。

我们在Android框架里,看到的更多的是这种情形。这种情况的实例,我们可以参

考Android 4.0 Camera实例,它相对而言比较独立,结构也比较简单.

  

 

原创粉丝点击