LINUX RTC機制實現計時器類

來源:互聯網
上載者:User

 

在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:<br />/*<br />* CTimer.h<br />*<br />* Created on: 2009-7-13<br />* Author: DEAN<br />*/<br />//////////////////////////////////////////////////////////////<br />// This class provide a timer to finish some works.<br />// Call StartTimer() to enable it and call StopTimer() to stop<br />// it. The work you want to do should be written on OnTimer()<br />// function. Call SetInterval(x) to set every x second to call<br />// OnTimer() once.<br />//////////////////////////////////////////////////////////////<br />#ifndef CTIMER_H_<br />#define CTIMER_H_<br />#include <sys/time.h><br />#include <linux/rtc.h><br />#include <sys/ioctl.h><br />#include <pthread.h><br />class CTimer<br />{<br />private:<br /> static CTimer *g_singleinstance;<br /> long m_second, m_counter;<br /> unsigned long m_data;<br /> int m_rtcfd;<br /> pthread_t thread_timer;<br /> static void *thread_stub(void *p)<br /> {<br /> (static_cast<CTimer*>(p))->thread_proc();<br /> }<br /> void *thread_proc();<br /> void OnTimer();<br />protected:<br /> CTimer();<br />public:<br /> virtual ~CTimer();<br /> static CTimer *Instance();<br /> void SetInterval(long second);<br /> void StartTimer();<br /> void StopTimer();<br />};<br />#endif /* CTIMER_H_ */<br />CTimer.cpp:<br />/*<br />* CTimer.cpp<br />*<br />* Created on: 2009-7-13<br />* Author: dean<br />*/<br />#include "Timer.h"<br />#include <iostream><br />#include <sys/time.h><br />#include <linux/rtc.h><br />#include <sys/ioctl.h><br />#include <sys/types.h><br />#include <sys/stat.h><br />#include <fcntl.h><br />#include <pthread.h><br />using namespace std;<br />CTimer *CTimer::g_singleinstance = 0;<br />CTimer::CTimer():<br /> m_second(2), m_counter(0)<br />{<br /> //Init the rtc<br /> m_rtcfd = open("/dev/rtc", O_RDONLY);<br /> if(m_rtcfd < 0)<br /> {<br /> cout<<"TimerWarning: open /dev/rtc error..."<<endl;<br /> return;<br /> }<br /> if(ioctl(m_rtcfd, RTC_IRQP_SET, 2) < 0)<br /> {<br /> cout<<"TimerWarning: Set rtc request failed..."<<endl;<br /> close(m_rtcfd);<br /> return;<br /> }<br /> pthread_create(&thread_timer, NULL, thread_stub, this);<br />}<br />//////////////////////////private methods//////////////////////////<br />void *CTimer::thread_proc()<br />{<br /> int nfds;<br /> while(true)<br /> {<br /> read(m_rtcfd,&m_data,sizeof(unsigned long));<br /> ++m_counter;<br /> if (m_counter >= m_second)<br /> {<br /> OnTimer();<br /> m_counter = 0;<br /> }<br /> pthread_testcancel();<br /> }<br />}<br />void CTimer::OnTimer()<br />{<br /> cout<<"Timer...."<<endl;<br />}<br />//////////////////////////public methods//////////////////////////<br />CTimer::~CTimer()<br />{<br /> pthread_cancel(thread_timer);<br /> pthread_join(thread_timer, NULL);<br /> close(m_rtcfd);<br />}<br />CTimer *CTimer::Instance()<br />{<br /> if (g_singleinstance == 0)<br /> g_singleinstance = new CTimer;<br /> return g_singleinstance;<br />}<br />void CTimer::SetInterval(long second)<br />{<br /> m_second = second * 2;<br />}<br />void CTimer::StartTimer()<br />{<br /> if (!(m_rtcfd > 0))<br /> {<br /> cout<<"TimerWarning: rtcfd < 0...Start failed..."<<endl;<br /> return;<br /> }<br /> if(ioctl(m_rtcfd, RTC_PIE_ON, 0) < 0)<br /> {<br /> cout<<"TimerWarning: ioctl(RTC_PIE_ON) failed..."<<endl;<br /> close(m_rtcfd);<br /> return;<br /> }<br /> m_counter = 0;<br />}<br />void CTimer::StopTimer()<br />{<br /> if (!(m_rtcfd > 0))<br /> {<br /> cout<<"TimerWarning: rtcfd < 0...Stop failed..."<<endl;<br /> return;<br /> }<br /> if(ioctl(m_rtcfd, RTC_PIE_OFF, 0) < 0)<br /> {<br /> cout<<"TimerWarning: ioctl(RTC_PIE_ON) failed..."<<endl;<br /> close(m_rtcfd);<br /> return;<br /> }<br />} 

 

linux 下 timer機制 標準實現,一般是用 sigalarm + setitimer() 來實現的,但這樣就與 select/epoll 等邏輯有所衝突,我希望所有 event 的通知邏輯都從 select/epoll 中觸發。(FreeBSD 中 kqueue 預設就有 FILTER_TIMER,多好)</p><p>ps. /dev/rtc 只能被 open() 一次,因此上面希望與 epoll 合并的想法基本不可能了~</p><p>下面是通過 /dev/rtc (real-time clock) 硬體時鐘實現的 timer機制。:-)<br />其中 ioctl(fd, RTC_IRQP_SET, 4) 的第三個參數只能是 2, 4, 8, 16, 32 之一,表示 xx Hz。</p><p>-------------------------------------------------<br />#include <linux/rtc.h><br />#include <sys/ioctl.h><br />#include <sys/time.h><br />#include <sys/types.h><br />#include <fcntl.h><br />#include <stdio.h><br />#include <unistd.h><br />#include <errno.h><br />#include <time.h><br />#include <err.h></p><p>int main(void)<br />{<br /> unsigned long i = 0;<br /> unsigned long data = 0;<br /> int fd = open("/dev/rtc", O_RDONLY);</p><p> if ( fd < 0 )<br /> errx(1, "open() fail");</p><p> /* set the freq as 4Hz */<br /> if ( ioctl(fd, RTC_IRQP_SET, 4) < 0 )<br /> errx(1, "ioctl(RTC_IRQP_SET) fail");</p><p> /* enable periodic interrupts */<br /> if ( ioctl(fd, RTC_PIE_ON, 0) < 0 )<br /> errx(1, "ioctl(RTC_PIE_ON)");</p><p> for ( i = 0; i < 100; i++ )<br /> {<br /> if ( read(fd, &data, sizeof(data)) < 0 )<br /> errx(1, "read() error");</p><p> printf("timer %d/n", time(NULL));<br /> }</p><p> /* enable periodic interrupts */<br /> if ( ioctl(fd, RTC_PIE_OFF, 0) < 0 )<br /> errx(1, "ioctl(RTC_PIE_OFF)");</p><p> close(fd);<br /> return 0;<br />}

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.