Linux rtc mechanism implementation Timer class

Source: Internet
Author: User

 

A timer is often used in LINUX, but in LINUX, it is not as convenient as SETTIMER () in WINDOWS. There are three main methods: SLEEP/USLEEP + separate thread; SETITMER adds Signal Processing SIGALRM or RTC mechanism. Here I am talking about using the RTC mechanism to implement the Timer class. This method is the most advantageous. It is separated from the SLEEP and SIGALRM signals in the traditional sense, and its operation is not affected by SLEEP, And SETITMER and so on will be affected by SLEEP, because they use the same clock.
The timer class (http://hi.baidu.com/susdisk/blog/item/03f70d35e8e2e182a61e1288.html) previously implemented with select is actually not a real timer, It is a loop, just stopped for one second after processing an ONTIMER () event, then, the next ONTIMER () is not a real timer. The real timer should be triggered no matter whether or not it is processing the ONTIMER () event.
RTC (real-time clock ). Now you can use the RTC mechanism in LINUX to write timer classes. This class is a timer in the full sense. After testing, it basically does not take up cpu time, because it uses the underlying hardware clock, the rtc documents clearly understand that the biggest difference between it and the system clock is that even if the machine consumes very low energy, this clock signal is also triggered. It is also completely independent from SLEEP, SETITIMER, and other functions. That is to say, using this Timer class, you can still use various SLEEP functions without affecting each other, I think this is the most important thing.
The implementation is as follows:

CTimer. h: <br/>/* <br/> * CTimer. h <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 shoshould be written on OnTimer () <br/> // function. call SetInterval (x) to se T 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 lon G 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/> * 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/> re Turn; <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/> 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/>} 

 

Standard Implementation of the timer mechanism in linux is generally implemented using sigalarm + setitimer (), but this conflicts with the logic such as select/epoll, I want the notification logic of all events to be triggered from select/epoll. (In FreeBSD, kqueue has FILTER_TIMER by default.) </p> <p> ps. /dev/rtc can only be opened () once, so the above idea of merging with epoll is basically impossible ~ </P> <p> The following is the timer mechanism implemented through the/dev/rtc (real-time clock) hardware clock. :-) <Br/> the third parameter of ioctl (fd, RTC_IRQP_SET, 4) can only be one of 2, 4, 8, 16, and 32, indicating 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/>}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.