Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2113482
  • 博文数量: 374
  • 博客积分: 7276
  • 博客等级: 少将
  • 技术积分: 5668
  • 用 户 组: 普通用户
  • 注册时间: 2011-10-06 16:35
文章分类

全部博文(374)

文章存档

2013年(23)

2012年(153)

2011年(198)

分类: LINUX

2012-05-29 11:32:59

在LINUX中经常要使用计时器,而在LINUX环境下使用计时器不像WINDOWS环境下那样一个SETTIMER()方便,主要有三种方式:使用 SLEEP/USLEEP+单独线程;SETITMER加处理信号SIGALRM,或者是RTC机制。这里我讲到的是使用RTC机制实现计时器类。这种方 法最为优越,它与传统意义上的SLEEP和SIGALRM信号是分离的,它的运行不受SLEEP的影响,而像SETITMER等都会受到SLEEP的影 响,因为它们使用的是同一时钟。
    以前用select实现的计时器类(http://hi.baidu.com/susdisk/blog/item/03f70d35e8e2e182a61e1288.html)其实并不是真正的计时器,它是一个循环,只是在处理完一次ONTIMER()事件后停下了一秒,然后再接着一次ONTIMER(),这其实并不是真正的计时器。真正的计时器应该是不管是否在处理ONTIMER()事件,它都会触发。
    RTC(real-time clock)。现在可以使用LINUX下的RTC机制来编写计时器类,这个类是完全意义上的计时器,经过测试,也基本不占用cpu时间,因为它采用的是底 层的硬件时钟,rtc的文档中说的很明白,它与系统时钟最大的区别在于即使它在机器耗能非常低的情况下,也会触发此时钟信号。它也与SLEEP、 SETITIMER等函数是完全独立的,就是说,使用这个计时器类,你依然可以使用各种SLEEP函数等,互不影响,这一点我觉得是最重要的。
    实现如下:

CTimer.h:
/*
* CTimer.h
*
* Created on: 2009-7-13
*      Author: DEAN
*/

//////////////////////////////////////////////////////////////
// This class provide a timer to finish some works.
// Call StartTimer() to enable it and call StopTimer() to stop
// it. The work you want to do should be written on OnTimer()
// function. Call SetInterval(x) to set every x second to call
// OnTimer() once.
//////////////////////////////////////////////////////////////

#ifndef CTIMER_H_
#define CTIMER_H_

#include
#include
#include
#include

class CTimer
{
private:
    static CTimer *g_singleinstance;
    long m_second, m_counter;
    unsigned long m_data;
    int m_rtcfd;
    pthread_t thread_timer;
    static void *thread_stub(void *p)
    {
        (static_cast(p))->thread_proc();
    }

    void *thread_proc();
    void OnTimer();
protected:
    CTimer();
public:
    virtual ~CTimer();
    static CTimer *Instance();
    void SetInterval(long second);
    void StartTimer();
    void StopTimer();
};

#endif /* CTIMER_H_ */


CTimer.cpp:

/*
* CTimer.cpp
*
* Created on: 2009-7-13
*      Author: dean
*/

#include "Timer.h"
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;

CTimer *CTimer::g_singleinstance = 0;

CTimer::CTimer():
    m_second(2), m_counter(0)
{
    //Init the rtc
    m_rtcfd = open("/dev/rtc", O_RDONLY);
    if(m_rtcfd < 0)
    {
        cout<<"TimerWarning: open /dev/rtc error..."<         return;
    }

     //设定频率 2Hz
    if(ioctl(m_rtcfd, RTC_IRQP_SET, 2) < 0)
    {
        cout<<"TimerWarning: Set rtc request failed..."<         close(m_rtcfd);
        return;
    }
    pthread_create(&thread_timer, NULL, thread_stub, this);
}

//////////////////////////private methods//////////////////////////
void *CTimer::thread_proc()
{
    int nfds;
    while(true)
    {
        read(m_rtcfd,&m_data,sizeof(unsigned long));
        ++m_counter;
        if (m_counter >= m_second)
        {
            OnTimer();
            m_counter = 0;
        }
        pthread_testcancel();
    }
}

void CTimer::OnTimer()
{
    cout<<"Timer...."< }
//////////////////////////public methods//////////////////////////
CTimer::~CTimer()
{
    pthread_cancel(thread_timer);
    pthread_join(thread_timer, NULL);
    close(m_rtcfd);
}

CTimer *CTimer::Instance()
{
    if (g_singleinstance == 0)
        g_singleinstance = new CTimer;
    return g_singleinstance;
}

void CTimer::SetInterval(long second)
{
    m_second = second * 2;
}

void CTimer::StartTimer()
{
    if (!(m_rtcfd > 0))
    {
        cout<<"TimerWarning: rtcfd < 0...Start failed..."<         return;
    }
    if(ioctl(m_rtcfd, RTC_PIE_ON, 0) < 0)
    {
        cout<<"TimerWarning: ioctl(RTC_PIE_ON) failed..."<         close(m_rtcfd);
        return;
    }
    m_counter = 0;
}

void CTimer::StopTimer()
{
    if (!(m_rtcfd > 0))
    {
        cout<<"TimerWarning: rtcfd < 0...Stop failed..."<         return;
    }
    if(ioctl(m_rtcfd, RTC_PIE_OFF, 0) < 0)
    {
        cout<<"TimerWarning: ioctl(RTC_PIE_ON) failed..."<         close(m_rtcfd);
        return;
    }
}



阅读(2160) | 评论(0) | 转发(2) |
给主人留下些什么吧!~~