诺基亚symbian 手册汇编3

Symbian操作系统将应用程序设计为单线程的,在大多数情况下等待异步事件的产生和完成。虽然可以使用多线程,但是不提倡这种做法,一方面是上下文切换开销导致电池使用寿命降低,另外一方面就是开发较复杂。    Symbian使用Active Object框架来处理操作系统的异步事件处理特性。由两方面构成:

  • The Active Scheduler: 用来调度事件,每个线程只能有一个
  • Active Objects:这些对象用于处理事件,在一个线程中可以有多个
Asynchoronous Functions     Symbian OS中包含很多异步函数,任何含有TRequestStatus&参数的函数都是异步的。如:

void After (TRequestStatus& aStatus, TTimeIntervalMicroSeconds32 aInterval)

  • TRequestStatus:包含一个TInt类型的状态值,调用时值为TRequestStatus
  • 时间请求当且仅当aStatus != TRequestStatus时完成,而非函数返回时完成
Synchoronous Functions    先看如下例子:创建一个Timer,并且请求一个10秒的timeout。

RTimer timer;

timer.CreateLocal();

TRequestStatus status;

timer.After(status, 10000000);

User::WaitForRequest(status);

    这是同步调用,即当User::WaitForRequest(status);执行时,其他事件都被挂起,用户界面停止响应。一个比较好的解决办法是:当时间请求结束后收到一个通知,而在该过程中其他事件可以被处理。

Active Objects       可以被用来处理异步函数调用。从CActive继承,并有如下成员变量:优先级决定了何时被检查是否完成

  • TRequestStatus:类成员变量,iStatus,传入异步函数调用
  • RunL():当异步请求结束时被调用
  • DoCancel():当异步请求被取消时调用
Active Scheduler    当应用程序启动时,都包含一个系统创建的默认Active Scheduler。在主线程中进行事件循环,完成以下功能;

  • 同步等待任何发出请求的结束
  • 根据优先级测试每个注册的active object,看是否有发出的请求、它的请求是否已经结束
  • 对于每个请求已经完成的active object,调用其RunL()函数
  • 在RunL()返回后,再检查其他请求
  • 对于RunL()可能Leave的情况,调用需函数RunError()
    通过 static void Add ( CActive* aActive)函数将一个active object注册到active scheduler中。

Implementing Active Objects

    要实现一个Active Object,必须遵循以下步骤:

  • 从CActive继承
  • C++构造函数中:设置优先级EPriorityStandard,调用CActiveScheduler::Add()
  • 提供一个进行异步函数调用的成员函数,传入:CActive::iStatus,调用CActive::SetActive()
  • 实现RunL()和DoCancel()函数,因为他们都是纯虚函数,必须实现
  • 在析构函数中调用CActive::Cancel()
    Symbian中的CPeriodic类已经是一个对timer封装的active object了。

诺基亚symbian 手册汇编3 - jianhai1229 - 水木博客

    上图展示了Active Object使用的调用流程。

Active Objects Other uses

  • 处理异步函数调用
  • 将处理器开销大的任务分成几个阶段
  • 实现一个异步服务
  • 调用一系列的异步函数

读后感    Active Object也是Symbian的特点之一,用来处理异步事件,相当于多线程的概念。

    使用过程中有很多pitfalls,要千万小心。

    虽然代码都能看懂,想通,感觉自己对她还不是非常了解......

    你的应用程序需要实现某个功能(如Bubble排序),你需要实现一个AO,并且设置一个回调函数,以便AO将结果通知UI。

peter (2007-11-04 16:05:20)

本课从用户角度学习客户端/服务器框架,关注如何使用客户端API而非实现服务器端功能。Introduction    Symbian OS使用客户端/服务器框架来访问系统资源:如打开文件、拨打、设置闹钟等。需要由服务器来管理系统资源来防止多个客户访问可能引起的问题。

    服务器运行在自己的进程或者线程空间中,任何来自客户端的请求都要穿过线程边界。这表明:服务器对资源有着绝对的控制权,可以拒绝来自客户端的请求(如一个客户端请求删除另外一个客户端正在编辑的文件)。

Example Servers and Client APIs    Symbian OS主要包含的服务器,如下图所示,其中:

诺基亚symbian 手册汇编3 - jianhai1229 - 水木博客

  • 蓝色:在自己的进程空间中
  • 绿色:在一个线程空间中,与其他服务器共享一个进程
     在每个Server中列出的类描述了客户端可以使用的API,以下是每个服务的概述:

Kernel Server:运行在最高权限,管理系统中所有其他进程对硬件和内存的访问。

  • RTimer:提供异步时间服务
  • RThread: 提供线程访问和创建
  • RSemaphre:提供线程间同步机制
File Server:提供了对文件系统的访问

  • RFs:提供到文件服务器的一个会话,可以完成高层次的驱动器、目录和文件的操作以及获取目录列表
  • RFile:提供文件创建、读取和写入操作
  • RDir:读取目录中所含的entries
Window Server:应用程序框架使用窗口服务器来处理按键事件以及进行屏幕显示操作

  • RWindow:提供屏幕显示操作,开发人员一般使用CCoeControl::Draw()
  • RAnim:与服务器端animation通信(服务器端高优先级drawing)
  • CWindowGc:提供屏幕绘图操作的图形上下文
Font and Bitmap Server:在客户端之间共享字体和位图

  • RFbsSession:负责与字体和位图服务器之间的一个会话,程序开发中一般不使用该类
  • CFbsBitmap:表示一个位图
  • CFbsDevice:表示一个用于显示位图的图形设备
Telephony Server:负责设备的功能

  • RTelServer:提供到服务器的工具级别的访问
  • RPhone:提供设备上操作
  • RLine:提供一路的操作
  • RCall:提供在某一路上拨打/接收的功能
Socket Server:提供通过多种媒体创建一个TCP/IP或者UDP的socket

  • RSocketServ:连接到Socket服务器,发现所有的协议
  • RSocket:提供连接到,接收和发送数据到另外一个socket的功能
  • RHostResolver:提供DNS解析功能
Comms Server:允许开发者通过电缆或者红外使用串行口

  • RCommServ:提供一个到Comms Server的会话
  • RComm:提供通过串行口通行的功能
Message Server:保存消息数据并且提供到消息功能如SMS,MMS,OBEX和Mail的访问

  • CMsvSession:描述一个和消息服务器的会话
  • CMsvEntry:描述消息stroe中的一个entry
  • CBaseMtm:提供访问和操作消息服务器entry的接口
Server Plug-ins    客户端/服务器架构具有很好的可扩展性,许多服务器都允许添加plug-in模块,为新的技术、协议和媒质提供功能。所添加的新功能可以通过一个generic api进行访问。如:

  • Message Server:MMS,SMS,POP3,SMTP
  • Socket Server:红外,蓝牙,CSD(Circuit Switched Data)
Sessions

    下图展示了不同的客户端/服务器会话场景:

诺基亚symbian 手册汇编3 - jianhai1229 - 水木博客

Client1:和服务器之间只有一个会话,在应用程序的control environment中与文件服务器的默认会话。

Client2:和服务器之间有两个会话,除默认会话外还有一个显式的文件操作。

Client3:和服务器之间有一个会话和两个字会话,与文件服务器有一个连接,对每个打开的文件分别由一个会话。

Requests    下图展示了一个客户端如何穿越线程边界与服务器进行通信,RSessionBase等类都是基类,需要继承。

诺基亚symbian 手册汇编3 - jianhai1229 - 水木博客

具体过程如下:

  • 调用一个客户端接口所提供的API,如RFs::Drive(),来获取驱动器信息
  • RSessionBase::SendReceive()被调用,参数为操作码和一个包含4个指向客户端内存指针的数组
  • 内部的private函数RSessionBase::SendSync()被调用,访问内核
  • 内核调用服务器线程中的CSession2::ServiceL(), 封装了消息内容的RMessage2作为参数
  • 调用RMessage2::WriteL()在用户端的空间中写入所需要的数据
  • 调用RMessage2::Complete()来表示对客户端请求的完成
Using Client APIs

    客户端API继承自RSessionBase或者RSubSessionBase,必须以以下顺序使用:

  • 建立到相应的服务器的连接,一般通过函数Connect()或者Open()。
  • 在建立连接后,可以使用所有的API,请求可以通过同步或者异步的方式发送。
  • 在使用完后必须关闭到服务器的连接,否则将发生资源泄漏
    需要注意的是:可能会发生leave,资源必须使用CleanupClosePushL()放到cleanup stack上。

    ClientAPI的使用案例:

HBufC* CFileUtil::ReadL(const TDesC& aFileName)

{

   RFs fs;

   User::LeaveIfError(fs.Connect());

   CleanupClosePushL(fs);

   RFile file;

   User::LeaveIfError(file.Open(fs, aFileName, EFileRead);

   CleanupClosePushL(file);

   TInt fileSize;

   file.Size(fileSize);

   HBufC8* data = HBufC8::NewL(fileSize);

   file.Read(data);

   CleanupStack::PopAndDestroy(2);

   return data;

}

读后感    这就是传说中的微内核设计?

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值