关于活动对象

  活动对象(一)
      理解活动对象还真不容易,从网上看了很多别人的见解、心得,但大多是断章取义,搞得自己总是一知半解。终于,还是从Nokia公布的一个范例中找到了一篇 文档,对这方面的知识作了系统的介绍。在知识体系里,活动对象有一些预备知识,包括多任务、多线程、协同式、抢先式、同步、异步以及Symbian的客户 端/服务器模式的微内核结构。这些都是理解和灵活运用活动对象的基础。这些知识都是操作系统里的基本概念,现在再回过头来看看大学里学的这门课程,感触颇 深。对当年林亨利老师的谆谆教诲和面对同学们的不屑一顾时的无奈和遗憾,似能体会一些了。
      此时此刻,对她说声谢谢吧,真心的。
      操作系统是一个程序员从know what向know how进阶的必经之路,大学欠下的东西,我会补回来。
      呵呵,跑题了。
     
       ,献给林亨利老师!
    
      多任务处理时操作系统中必不可少的一项技术,用来处理几个独立的任务间如何共享同一个处理器。Symbian中的多任务体现在多线程和活动对象上。
      对多任务的调度,可以有协同式和抢先式两种。协同式,即依据一定的算法,使处理器适时地将某个进程挂起,使某个进程执行。抢先式,即设定了一个时间片,处 理器使每个任务在每次只运行固定的时间,如此循环,保证每个任务都能得到一定的运行时间。不同的操作系统根据所部属的硬件平台特性和应用领域的不同,适当 地选取多任务处理策略,以期满足不同用户的需要。
      Symbian中,对于多线程,采用的抢先式多任务处理,这样可以运行多个应用和多个服务器。如可以同时完成窗口服务器的交互任务和文件服务器的读写文件 任务,而不会给用户特别不顺畅的感觉。其实,并不是这两项任务一起执行的,只是采用了非常适合的多任务调度策略的结果。对于线程中的各个活动对象,它们也 是多任务。对它们的处理则采用非抢占式的多任务处理。

  活动对象(一)

      活动对象用于在单一线程内实现非抢先式的多任务,简言之,活动对象是线程的子任务。既然活动对象是非抢先式的,也就是说一个作为活动对象的任务在运行时,必然阻塞其余任务的运行,这难道不会用户的使用造成不连续的感觉吗?
      Symbian利用其客户端/服务器模式,提供了很多异步方法。活动对象里发出异步请求,从而巧妙的解决了这一问题。
      Symbian OS以服务器的方式提供了一些服务,如文件服务器提供了对文件系统的操作。这时程序员编写的程序作为客户端程序,需要首先建立和服务器的连接,然后向服务 器发送请求,完成某项操作。如读文件、写文件。这时就产生了两个线程,服务器线程和客户端线程。我们只关注客户端线程,因为这是需要你编写的。
      以RFile为例。客户端线程里有一些活动对象。在每个活动对象里调用一些请求服务器服务的方法,如读文件。当调用这种方法调用时,客户端只是向服务器发 送了一个消息,这个消息里包括请求的操作和数据,仅此而已。真正的数据处理在服务器端完成,这是系统调用,程序员不用理会。客户端发送消息的过程很短,而 服务器端处理数据的过程可能很长。那么,在客户端,没有必要等待服务器的完成,可以在发送完消息后,立即执行活动对象中后面的语句。当服务器完成数据处理 后,会通知客户端,调用RunL()函数执行,RunL()完毕后,该活动对象结束,活动调度器会启动下一个等待请求的活动对象。
      将请求和数据处理分开在两个线程里执行,数据处理完成后对请求进行追踪处理,保证逻辑上的有序性,这就是异步方法。它可以缩短活动对象的运行时间,用户的体验将非常良好。

终于把活动对象想明白了

Symbian也是多任务操作系统,当然也要用进程、线程完成多任务处理。进程是程序的运行实例,有自己独立的数据空间。线程是进程的执行单元,一个进程至少有一个主线程。
多线程可以并发运行采用抢占式完成多任务处理。但是Symbian下不提倡使用多线程,因为Symbian系统是通过客户端/服务器结构来提供对线程资源的访问,这就意味着访问线程需要与内核的服务器程序不断地进行通信,效率低。
     在单线程内,配合使用活动对象+异步函数,完全可以模拟多线程并行运行。不同的是,这是一种非抢占式并行运行,即当前活动对象结束之前,其它活动对象不能运行。
     异步函数在执行后立即返回,继续执行它下面的代码。异步操作有后台继续执行,结束后通过信号量表示异步操作结束。同步函数必须函数内所有操作全部执行结束后才能返回,执行下面的代码,否则就阻塞在那里。很显然,实现多任务并行运行必须使用异步函数。
     活动对象是CActive的派生类,设立它的作用就是为了提供一个专门用来调用异步函数的类。因为这个类中专门设有回调函数,使异步函数结束后,能利用这 个回调函数进行尾处理。这个函数就是RunL()。在活动对象外面使用异步函数,只能截获信号量,不能直接进入某个回调函数。
     异步函数结束后,是如何进入到正确的回调函数中的呢?系统运行着一个活动调度器(CActiveSchedule),它能截获异步函数结束后发出的信号 量,并根据这个信号量,调用相应的RunL()。问题是如果CActiveSchedule截获了这个信号,但却找不到该调哪个活动对象的RunL()怎 么办?这时CActiveSchedule会抛出异常,这种状态叫信号游离,这种状况经常发生,所以使用活动对象应该避免这种情况发生。
     哪些情况会产生游离信号?理解这个问题首先要了解CActiveSchedule如何判断这个信号是不是游离信号。CActiveSchedule判断游离信号的条件是
for(I=0;I<NUMBERS_OF_ACTIVE_OBJECT;I++)
{
    IF(ACTIVE_OBJECTS[I].iActive==ETrue&&ACTIVE_OBJECTS[I].iStatus!=KRequestPending)
    {
    //由此可见,规则有二
    //规则1 根本就没有这个活动对象
    //规则2 活动对象不是“活”的
    ACTIVE_OBJECTS[I].RunL();
    }
}
所以有如下情况可能会导致出现游离信号出现
1.没有调用CActiveSchedule::Add(this);把活动对象加到活动调度器中。
2.没有调用SetActive把活动对象激活。破坏规则(2)
3.在活动对象外调用异步函数后,没有用User::WaitForRequest()截获异步函数完成信号量。信号量进入循环却找不到活动对象,破坏规则1。
4.同时一个活动对象中同时调用两个异步函数。如:InvokeAsyncFunc1();SetActice(); InvokeAsyncFunc2();SetActive();第一个异步函数结束后,执行完回调函数RunL()后,会把iActive置为 EFalse,这时第二异步函数的结束信号进入时,却发现活动对象不是“活”的,破坏规则2。
所以在一个活动对象不能同时调用多个异步函数。


来源于:
http://casper1314.spaces.live.com/?_c11_BlogPart_pagedir=Next&_c11_BlogPart_handle=cns!5C29B0743964E16!159&_c11_BlogPart_BlogPart=blogview&_c=BlogPart
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值