ril驱动解析

 一.RIL 概述
   目前的智能机在硬件上多采用双cpu的架构,一个是基带处理器,主要处理数字信号、语
音信号的编码解码以及GSM通信协议,另一个是应用处理器,运行操作系统和各种应用程序。
基带处理器、射频和其它外围芯片作为一个模块,成为GSM/GPRS modem,提供AT命令接口。
网络的应用已经是一个需求的热点,而目前的GSM模块大都能支持GPRS功能。应用处理器
通过AT命令集与带GPRS功能的无线通讯模块通信,
                                             为实现网络的应用提供了一个最底层的
持。
   从软件的角度来看,RIL(Radio
                                Interface Layer
                                               )工作在PPP、TCP/IP协议之下,负责数
据的可靠传输、AT命令的发送以及response的解析。当然,除了对网络的支持,RIL也支持
SMS、Voice Call等功能。从这一点来看,RIL的性能好坏影响着所有无线通信应用相关的软
件,而软件设计的合理性又影响着RIL的性能。
   Windows Mobile是用在智能手机上的主流操作系统之一。微软是这样介绍RIL的:作为
Windows Mobile的一个非常重要的组件,RIL使各种无线语音和数据应用成为可能。运行在
Windows Mobile上的软件可以通过RIL无缝地与GSM/GP
                                                 RS或者CDMA2000 1X
                                                                    modem通信。RIL
的位置处于无线基带系统的协议栈之上,Windows Mo
                                                bile的CellCore层之下。由于RIL隐藏
了硬件上的一些细节,OEM厂商可以根据自己的需要将不同型号的无线modem集成到它们的产
品之中。
      Windows Mobile 提供了RIL 的源码,因此在RIL上的开发工作相对来说比较简单了,主
要是根据不同厂商对AT命令以及Telephony features的差异对RIL做一些局部的修改和调
试。
      但美中不足的是,微软没有提供 RIL 的设计文档,而且关于 RIL 架构的介绍也是最高层
的,不能够很深入地了解 RIL 的设计者在构建这个复杂组件时考虑了哪些问题,又是基于哪
些思想和方法来解决的,最终又是如何把一个个的片断整合起来形成一个精密运转的系统
对我们而言,一个现实的途径就是通过对源码的分析把这个过程动态地还原出来。
      这样做有什么意义?第一,在了解工作原理和结构后,有助于我们在 RIL 开发过程中能
够顺利地解决问题。第二,有利于积累设计经验和提高自己的设计水平。这一点也许是最重
要的,"他山之石,可以攻玉"。在吸收和掌握了 RIL 的设计思想后,也可以在自己的手机平
台上实现自己的 RIL。
      当然,关于 RIL 的可讨论的问题很多,对于每一个关键的设计问题都可以单独作为一
主题来阐述。由于重点是放在介绍 RIL 背后的的设计思想,所以尽量砍去旁支末节,而是专
注于基本问题和方法的讨论。要真正理解这些人怎么想的,所以最好的方式是动态地展现整
个思考过程,去模仿它们的足迹而不是生硬地 copy。
      RIL 控制的设备是无线 modem,面临的第一个问题就是怎么把数据发送出去,又怎么接收
发给自己的数据。整篇其实就是围绕这个问题展开的,最终使我们的系统能够建立起数据传
输的双向通道,让数据有效率地往返流动。
二.应用场景和问题域
   如图 1,手机中的 GSM/GPRS modem 支持呼叫控制、SMS、GPRS 等功能,以 AT 命令
方式提供了通信接口。对于每一个 AT 命令,Modem 都回返回一个 solicited response。现在
有两个应用程序:SMS_App1 和 SMS_App2。从用户的角度来看,要做到这两个应用程序能
够并发地运行。      

 


                                                                               
      作为设计的起点,能够很自然想到需要提供一个基础设施 RIL,为应用程序提供无线通
信相关的服务,包括呼叫控制、短消息、GPRS 等功能。而且对于上层应用程序来说,可以
抽象地把 RIL 看作逻辑设备,它只需要和 RIL 通信就能够获得所需要的服务。RIL 是一个典
型的生产和消费数据的设备,所以暴露的接口可以按照 Stream I/O 的规范来设计。这样做
还有一个好处就是,应用程序可以把设备看作文件,通过文件接口来访问 RIL.如图 2,我们
最初步的层次模型。

 

 

                                                                                     
       RIL_XXX 是提供给 DeviceManger 的 stream Interface,在 RIL Service 这一层,Dispather
将 request code 分发给相应的 function,例如 SMS。然后 SMS  的 function  发消息给 RIL
Device  将请求以 AT 命令的形式发送给 GSM modem。
    在这个基础上,我们可以慢慢展开我们的分析和设计过程了。
       首先,我们先根据我们的应用场景提取出一些设计时要考虑的问题:
1.RIL 必须能够同时为多个请求者提供服务。
2.AT 命令必须与 Response 的绑定,即 AT  命令的发送者、AT 命令和 Response 之间对应关
     系必须得到保证。
3.I/O 效率比较高。
4.需要 Notification 机制。
  这里面有两层意思:1.怎么把 Response 交给应用程序;2.在多用户环境下,怎么判断该把
Response 交给哪个应用程序。
5. modem 对 AT 命令的处理是串行的,只有第一个 AT 命令发送后才能发送第二个 AT  命令。

 


   
   6.  程序向 modem 发送 AT 命令,除了 unsolicited response 之外,基本的交互模式就是请求--
        应答模式,即对每一个 AT 命令必须收到一个 solicited response。
         其次,为了方便讨论和不过早地涉及到细节问题,对我们的模型作一些理想化的假设:
   1.AT命令总是能够通过串口设备发给modem,然后modem又能够通过空中接口发送给基站。总
   而言之,在数据的传输过程中,每一个环节都是可靠的,不可能出现数据丢失,数据错误的
   问题。
   2.对于每一个 AT 命令,modem 都会返回一个 response,不会出现没有应答的情况。
            接下来,我们要界定问题域的边界,弄清我们的原型与外界环境的关系,明确 RIL 所处
   的位置。当然,我们里的环境就是 windows mobile 软件的总体架构,RIL 作为这个精巧系
   统的部件,必须协调好与其它部件关系才能够发挥正常的功能。
         如图 3,着色的部分正是我们所关注的问题域。我们从整个系统的角度来观察 RIL 的工
   作流程。RIL Stub 和 RIL Dri
                                  ver 拥有自己的线程,名为 RILThread。应用程序调用 RIL
   的工作流程如下:

 

 

                                                                               
   1.应用程序的进程在自己的进程空间里,以调用RIL Proxy方式发送请求。
   2.RIL Proxy 以IPC方式穿越进程边界,把请求传给 Device Manager。
   3.Device Manan
                   ger 根据操作码,将请求分发到相应的驱动程序,在这里当然是 RIL。
   4.RIL Stub首先接收操作码,根据PID做
                                          Context切换,然后把请求转发给R
                                                                          IL Driver。
   5.现在 RIL Driver 已经处于对应于用户进程的 Context 中,开始处理操作码。例如,
                                                                                        将
   AT 命令发给 GSM modem,等待返回的 response。当然,RIL Driver 运行在自己的线程里。
                                                                                              
      为了做到
                RIL  驱动能为多个应用(在这里就是进程)同时提供服务,RIL Stub需要做这
   两件事情:
   1.为每一个进程创建一个Context  对象,用来维护处理应用程序请求时的一些私有数据,我
   们可以用一个类来表示就是CRilInstance。
   2.当应用程序向DevieManger发送操作请求时,DeviceManager  将RIL切换到适当的Context,
   然后将请求发给 RIL。
         下面是CRilInstance 的创建过程:
   1.在用户进程里,调用RIL Proxy 的接口 RIL_
                                                 Initialize()获得 RIL的一个实例。
   2.DeviceManger 将请求分发给 RIL 。
   3.RIL Stub 将请求转换为生成 RilInstance 的一个实例。ILStub 调用 RIL Driver 的
   RIL_Open 做到这一点,生成的 Context 都由 RIL Driver 来管理。

 


 
三.同步 I/O 方案
     图 4 给出类之间的关系和它们的接口,下面介绍一些主要类的 role 和 responsibility。

 

 

                                                                                          
(1)CCommand
role:对AT 命令的封装。
(2)CResponse:对Re
                     sponse的封装。Modem通过串口
                                                    返回的response是一串字符,我们把它封
装在这个类里面。
(3)CNotification:为了程序处理的方便,我们会将r
                                                      esponse映射为一系列的no
                                                                               ification
code,封装在CNotification里面。
       这些类的responsibility我们将在后面慢慢地明确。
(4)CRilNotificationQueue
role:管理对缓冲区的访问,这个缓冲区是队列的形式组织的。
responsibility:
1.出队、入队的操作。
2.数据保护,当队列在多个Thread Context中被调用时,需要保护共享资源的机制。
(5)CRilHandle:RIL  驱动对象。
role:从客户的角度看,把它看作逻辑上的无线设备。
resposibility:
1.管理 RIL 设备的 open context,即对应 CRilInstanceHandle。
2.打包 AT 命令。
3.对串口设备的访问和操作。
4.通过串口将 AT  命令发送给 modem。
5.接收 modem  返回的 response
6.解析 response ,  解析结果放在 notification 里
7.通知应用,AT 命令处理后的结果
8.modem 状态的维护
(6)CRilInstance: RIL 的 Open Context
role:每个应用程序在 RIL 的 context,
responsibility:
1.  管理 notification queue
2.  为应用  提供接口,取出 notification
       图 5 是同步 I/O 过程。在 SendCmdWithRsp()里面,SendCmd()和 WaitRsp()被耦合在一
起,只有读写的操作都完成后,函数才会返回。在返回之前,会将解析出来的 response 放进

 


CRilNotificatioQueue 里存储起来。

 

 

                                                                                      
 
     上面的设计存在两个问题:
     1.I/O 的效率很低。原因有两点:
(1)对串口的读写都是同步方式  
(2)读写耦合紧密,也就是 AT 命令的写和读该命令的 response 是绑定在一起的。
       这种模式的好处是:读的操作和写的操作处理起来都非常简单,不需要复杂的
notification 机制;容易满足请求——应答模式的要求。缺点就是:由于操作的藕和太过于紧
密,而且读写的操作都是堵塞的,这样会导致系统 I/O 效率低。对于通信软件来说,系统的
吞吐量和时间上的响应延迟都是要求较高的,而我们的设计不能适应这种要求。
     2.Responsibilty 分配不均衡。CRilHandle 承担了太多的工作,造成性能瓶颈。我们可以创
建新的类,分解 CRilHandle 任务,把它们分配给这些新类。
四.异步 I/O 方案
       前面的设计方案由于性能的原因不太可取,但我们可以在它的基础上作进一步的改进。
我们的基本思路就是有两点:
       1.将同步 I/O 改为异步 I/O,当然这样做技术上的难度会增加。  
       2.分解 CRilHandle 的职责。
       整个系统可划分为两大部分:命令的发送部分和 response 的接收部分。我们先考虑命
令发送部分。为了使关注问题更集中,只考虑 AT 命令发送部分,并且不考虑超时机制,也
不考虑可靠传输机制和错误处理机制。
       改进后的 Class Diagram 如图 6 所示。相对于原来的 Class Diagram,我们主要做了这些
改动:
     1.增加一个新的类 CComHandle,作为 modem 的代理,负责对 modem 的读写,以及 modem
状态维护。这样,CRilHandle 的职责就相对简单了
     2.将同步写改为异步写。为此我们需要开一个缓冲区 CRilHandle 将 AT Command 写进缓
冲区后就完成了写操作返回;然后 CComHandle  从缓冲区取出 AT Command  ,把它通过串
口发送出去。
     3.对于缓冲区,我们可以采用队列的数据结构,在这里我们用 CQueue 管理这个队列。

 


                                                                         
现在有几个问题要考虑:
  1.谁来驱动CComHandle工作?可以把CComHandle定义为active object对象,它能够主动
完成这些任务:先从缓冲区取出AT Command ,然后将A
                                               T Command发送给modem。为此,
CComHandle需要有属于自己的Thread Cont
                                       xt,我们将它定义为CommandThread 。
  2.对象之间如何协作?
  一种方式是让对象之间直接去交互,
                                   例如让CRilHandle和CComHa
                                                         ndle去调用CQueue提供的
接口。但有两点使得这个方式不合适:
 (1)从类定义的role来说,CRilHandl
                                   e 和CComHandle都是设备的抽象,不应该去与CmdQue
打交道,所以这上述方法就不合适。
 (2)耦合紧密。如果将来换一种缓冲区管理模式,例如不用队列改用池,还得需要修
CRilHandle 和CComHandle的实现。
   因此,可以使用另一种协作方式:从概念上假设有一个rganizer,通过调用这些类的接
口,把这些类的活动有机地组合起来以完成某个任务。这样不同的对象之间就用不着直接发
生交互了,而如果把这个概念映射到软件的设计上就是抽象出来的一个更高级的函数模块。
    如图7、8给出了类之间的协作关系和发送命令的过程。Ccommand和CrilHandle的接口我
们在后面的讨论中才能确定下来。

 

 

                                                                              

 


                                                                                
 
  3.共享资源的并发控制问题。 CComman
                                     dQueue跨越了两个Thread Context 边界,如果不
采用并发控制策略,在不同的context切换过程中,会导致对数据的操作产生逻辑错误。我
们可以把这个问题归为producer/consumer模型,然后制订我们的控制策略。
  首先得考虑下面的问题:
     (1)为了不使并发控制策略影响这个系统架构,希望将并发控制策略封装起来。
     (2)为了简化设计,put(),get()为堵塞式(暂时不考虑超时机制)。
     (3)较小的资源开销。加锁的粒度太大,时间太长都会降低系统运行效率;另一方面,
度使用mutex、event和semaphore都会消耗系统资源。
   下面给出共享资源的并发控制策略:m_nUsed 用来标志队列剩余的资源个数。不管是读还
是写操作,在访问m_nUsed时先申请锁,在获得锁之后对临界资源进行操作,然后解锁并发
信号唤醒堵塞在该信号上的任务。
      如图9所示,由于锁的粒度很小,put与get竞争的域较小,在系统资源和时间开销上
小。

 

 

                                                                           
      如图 10,11.依据相同的设计方法,给出 response
                                                 的接收部分。在 ResponseThread 里
面,先从 ComHandle 读取数据保存在 CRilH
                                       andle 的缓冲区里,然后创建一个 CResponse 对

 


象,由 CResponse 负责解析,接下来就将 CResponse 放进队列里面。

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/mbtrend/archive/2008/09/15/2931600.aspx

你可能感兴趣的:(thread,windows,command,Semaphore,mobile,sms)