异步机制, 活动对象,CTime,RTime

1. 异步事件
   Symbian OS 中异步函数最显著的特征是拥有TRequestStatus& 类型的参数.
   异步函数本身不提供服务,提供服务的是其他程序,所谓的服务提供者.
基本原理: 应该程序调用异步函数时指向服务提供者发送一个请求,发送完毕后函数调用返回,应用程序继续执行的
同时,服务提供者会处理该请求,处理完毕后服务器提供者向应用程序发送一个异步事件,接收到事件后应用程序才能
知道请求的服务是否完成.
   Symbain OS 推荐的处理异步事件的方法有两种,:
   第一种是使用信号量机制User::WaitForRequest()静态函数等待异步服务器完成.
   ......
   TRequestStatus status;
   AsyncFunction(status);
   User::WaitForRequest(status);//等待异步服务完成
   ......
   第二种是使用活动对象机制,效率高,也不会阻塞应用程序,下面我们学习...

2. 活动对象机制
   活动对象机制包括两个比较重要的概念:活动调度器和活动对象.
---------------------------------------基础部分-----------------------------------------------------
-
   (1) 活动调度器
   活动调度器维护着一个优先级队列,该队列存放着应用程序中所有活动对象.应用程序可以调用CActiveSchcdulc
r::Add()
静态函数将新建的活动对象添加到这个队列中.

   主要作用是:  分发和接收异步事件 。应用程序的活动调度器最先接收到异步事件,随后他会从队列中选出处于
活动状态而优先级最高的活动对象,先将它的状态置成非活动,然后将事件分发给它处理.
   CActiveSchcdulcr : public CBase
     {
     public:
       ...
       static void Add(CActive* anActive);
       ...
     private:
             ...
             TPriQue<CActive> iActiveQ;//活动对象队列
     }
    (2) 活动对象
    活动对象是CActive类子类的对象.
    class CActive : public CBase
    {
     ...
     public:
       ~CActive();
       void Cancel();
       void Deque();
       ...
       inline TBool IsActive() const;
       ...
     protected:
             CActive(TInt aPriority);
             ...
             virtual void DoCancel() = 0; //取消异步请求
             virtual void RunL() = 0; //活动对象的事件处理函数
             virtual TInt RunEror(TInt aError);
     public:
             TRequestStatus iStatus; //状态标记,指示异步事件完成状态
             TBool iActive;//活动标记,对象是否活动状态,是否等待异步事件
    }
    
    主要作用: 发送(取消)异步事件,处理异步事件,一个活动对象一次只能处理一个异步事件.
    
--------------------------------实践部分----------------------------------------------
我们分为两步分讨论: 活动对象和运行机制
   (1) 实现活动对象
   //CMyActive.h
   ...
   class CMyActive : public CActive
     {
     public://构造函数和析构函数
            static CMyActive* NewL();
            void ConstructL();
            ~CMyActive();
             CMyActive();
           
     public: //新定义的函数
       void IssueRequest(); // 发送异步请求函数
     public: //继承CActive类的函数
             void DoCancel(); //取消请求函数
             void RunL();//事件处理函数
             TInt RunError(TInt aError);//处理 RunL()抛出的异常
       ...
     }
   //CMyActive.cpp
   /*
   活动对象的优先级
   EPriorityIdle       用于在后台利用系统空闲时间处理不太紧迫的批量任务
   EPriorityLow        低于标准优先级
   EPriorityStandard   用于处理一般的前台任务
   EPriorityUserInput  用于处理用户输入
   EPriorityHigh       用于处理更高优先级的任务,如屏幕刷新
   */
   //指定活动对象的优先级
   CMyActive :: CMyActive():CActive(CActive::EPriorityStandard)
     {
     ......
     }
   //将活动对象添加到活动调度器
   void CMyActive :: ConstructL()
     {
     CMyActiveScheduler :: Add(this);
     }
    //实现异步请求
    void CMyActive :: IssueRequest()
     {
     AsyncFunction(iStatus);
     SetActive();
     }
    //取消异步事件
    void CMyActive :: DoCnacel()
    {
    ......
    }
    // 实现异步事件处理
    void CMyActive::RunL()
     {
     if(iStatus.Int() == KErrNone)
      {
      //请求的服务成功完成,加入处理程序
      }
     else
         {
         //加入错误处理代码
         }
     }
    //处理异常处理
    void CMyActive ::RunError()
    {
    ...
    }
    //实现析构函数
    void CMyActive :: ~CMyActive()
     {
     Cancel();
     }
    (2) 运行机制
    活动对象 ----> 服务提供者 ----> 活动调度器 -----> 活动对象
                                               -----> 活动对象
                                               -----> 活动对象
     如上图
     第一步: 活动对象调用IssueRequest()向服务提供者发送异步请求.调用之后活动对象的状态标记iStatus
成员被异步函数AsyncFunction()设置成KRequestPeding,活动标记iActive被SetActive()函数设置成ETrue.IssueRequest()
调用返回后应用程序照常执行, 同时服务器调用者处理收到请求.
     第二步: 服务提供者成功处理完请求后将活动对象状态标记iStatus设置成KErrNone(不成功设置为错误代码),然后向
应用程序发送一个异步事件.
     第三步: 活动调度器接收到异步事件后在他的优先级队列中寻找iActive值是ETrue值,iStatus值是KRequestPeding
的活动对象.从中选择一个优先级最高的,将他iActive设置成EFalse,然后调用它的RunL().

-----------------------------------------------------------------------------------------------------------

定时器服务
1. 同步定时器服务
   ----------------------------------
   User :: After(1000000)//延时1秒钟
   ----------------------------------
   ...
   TTime time;
   time.HomeTime();//获取当期那系统的时间
   time.TTimeIntervalMInutes(1); //指定目标时间(比当前系统时间晚1分钟)
   User::At(time);//延迟1分钟

2. 异步定时器服务
   解析:通过RTimer类提供异步定时器服务,通过该类向系统发送异步请求,是系统满足某些条件时向应用程序发送异步事件,
 请求包括:
   * 在指定的时间间隔之后发送一个异步事件
   * 在指定的时间发送一个异步事件
   void At(TRequestStatus& aStatus, const TTimer& aTime);
   * 在一秒中固定的时间段发送一个异步事件
   void Lock(TRequestStatus& aStatus, TTimerLockSpec aLock);
   * 在指定的时间间隔内没有用户活动(例如按键)时发送一个异步事件.
   void Inactivity(TRequestStatus& aStatus, TTimeIntervalSeconds aSeconds);
   RTimer类
   ...
   RTimer timer; //此时无定时器与timer相关联
   User::LeaveIfError(timer.CreateLoacal());//创建定时器
   timer.close();
   //1秒后iTimer所属的活动对象调度运行
   ...
   iTimer.After(iStatus, 1000000); // iTimer是RTimer类的对象
   SetActive();
   ...
   转换成同步操作
   TRequestStatus status = KRequestPeding;
   timer.After(status, 1000000);//发送异步请求
   User::WaitForRequest(status);//同步等待请求完成
  
   ----------------------------------------------------
   //计算运行时间
   ...
   TInt period;
   User::LeaveIfError(IIalData::ESystemTickPeriod, period);
   TUint start = User::TickCount();//获取起始时刻的滴答数
   //执行一段代码
   TUint end = User::TickCount();//获取终止时刻的滴答数
   TInt64 runtime = end -start;
   runtime *= period;//计算运行时间
   ...
   -----------------------------------------------------
   CTimer类
   简单的实现过程:
   CMyTimer :: CMyTimer():CTimer(EPriorityStandard)
   {...}
   void CMyTimer::ConstrutL();
     {
     CTimer :: ConstrutL();//创建定时器对象
     CActiveScheduler::Add(this);
     }
    void CMyTimer :: Start(const TTime& aTime)
        {
        Cancel(); //防止重复发送请求
        TTime now;
        now.HomeTime();
        iTargetTime = now.Int64() + aTime.Int64();//记录时间
        After(KInterval);//发送请求
        }
     void CMyTimer :: RunL()
      {
      TTime now;
        now.HomeTime();
        TTime time = iTargetTime.Int64() - now.Int64();//计算剩余时间
        if(time.Int64() > 0)
         {
         After(KInterval);//如果没有倒数到0继续请求定时器事件
         }
        else
         {
         time = 0;
         }
        iObserver.OnTimerL(time);
      }

以上是简单的分析,了解一些API函数和概念,在手机病毒分析中参考.

posted @ 2012-12-23 17:33  小金马  阅读(331)  评论(0编辑  收藏  举报