Linux下的定時器類實現(select定時+線程)


     更好的計時器類實現:LINUX RTC機制實現計時器類(原創)

      很多時候需要在LINUX下用到定時器,但像setitimer()和alarm()這樣的定時器有時會和sleep()函數發生沖突,這樣就給編程帶來了很大的困難。
    寫了一個定時器的類,使用select進行精確定時。而且可以在系統中創建不限數量的定時器,且互不干擾。類的內部采用線程實現。即線程+select。代碼如下:

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

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

#ifndef CTIMER_H_
#define CTIMER_H_

#include <pthread.h>
#include <sys/time.h>

class CTimer
{
private:
    pthread_t thread_timer;
    long m_second, m_microsecond;
    static void *OnTimer_stub(void *p)
    {
        (static_cast<CTimer*>(p))->thread_proc();
    }
    void thread_proc();
    void OnTimer();
public:
    CTimer();
    CTimer(long second, long microsecond);
    virtual ~CTimer();
    void SetTimer(long second,long microsecond);
    void StartTimer();
    void StopTimer();
};
#endif /* CTIMER_H_ */

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

#include "CTimer.h"
#include <iostream>
#include <sys/select.h>
#include <time.h>
#include <pthread.h>

using namespace std;
//////////////////////////public methods//////////////////////////
CTimer::CTimer():
    m_second(0), m_microsecond(0)
{
}

CTimer::CTimer(long second, long microsecond) :
    m_second(second), m_microsecond(microsecond)
{
}

CTimer::~CTimer()
{
}

void CTimer::SetTimer(long second, long microsecond)
{
    m_second = second;
    m_microsecond = microsecond;
}

void CTimer::StartTimer()
{
    pthread_create(&thread_timer, NULL, OnTimer_stub, this);
}

void CTimer::StopTimer()
{
    pthread_cancel(thread_timer);
    pthread_join(thread_timer, NULL); //wait the thread stopped
}

//////////////////////////private methods//////////////////////////
void CTimer::thread_proc()
{
    while (true)
    {
        OnTimer();
        pthread_testcancel();
        struct timeval tempval;
        tempval.tv_sec = m_second;
        tempval.tv_usec = m_microsecond;
        select(0, NULL, NULL, NULL, &tempval);
    }
}

void CTimer::OnTimer()
{
    cout<<"Timer once..."<<endl;
}

示例代碼main.cpp:
/*
* main.cpp
*
* Created on: 2009-7-19
*      Author: DEAN
*/

#include <iostream>
#include "CTimer.h"

using namespace std;

int main()
{
    CTimer t1(1,0),t2(1,0);    //構造函數,設兩個定時器,以1秒為觸發時間。參數1是秒,參數2是微秒。
    t1.StartTimer();
    t2.StartTimer();
    sleep(10);
    return 0;
}

    使用的話其實很簡單,只要寫一下OnTimer()函數的內容就行了,定時器會在每個定時器觸發時調用此函數。里面用到的一個點是使用類的成員函數作為線程體的執行函數,需要進行一下靜態類型轉換。在上面已標出:
    static void *OnTimer_stub(void *p)
    {
        (static_cast<CTimer*>(p))->thread_proc();
    }
    有了這個類以后,使用定時器就方便多了:-)

///LINUX RTC機制實現計時器類(原創) ///////////

在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函數等,互不影響,這一點我覺得是最重要的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM