Linux下实现定时器Timer的几种方法

来源:互联网 发布:淘宝详情页免费模板 编辑:程序博客网 时间:2024/05/21 06:54

http://blog.csdn.net/lxmky/article/details/7669296

定时器Timer应用场景非常广泛,在Linux下,有以下几种方法:

1,使用sleep()和usleep()

其中sleep精度是1秒,usleep精度是1微妙,具体代码就不写了。使用这种方法缺点比较明显,在Linux系统中,sleep类函数不能保证精度,尤其在系统负载比较大时,sleep一般都会有超时现象。

2,使用信号量SIGALRM + alarm()

这种方式的精度能达到1秒,其中利用了*nix系统的信号量机制,首先注册信号量SIGALRM处理函数,调用alarm(),设置定时长度,代码如下:

[cpp] view plain copy
  1. #include <stdio.h>  
  2. #include <signal.h>  
  3.   
  4. void timer(int sig)  
  5. {  
  6.         if(SIGALRM == sig)  
  7.         {  
  8.                 printf("timer\n");  
  9.                 alarm(1);       //we contimue set the timer  
  10.         }  
  11.   
  12.         return ;  
  13. }  
  14.   
  15. int main()  
  16. {  
  17.         signal(SIGALRM, timer); //relate the signal and function  
  18.   
  19.         alarm(1);       //trigger the timer  
  20.   
  21.         getchar();  
  22.   
  23.         return 0;  
  24. }  
alarm方式虽然很好,但是无法首先低于1秒的精度。

3,使用RTC机制

RTC机制利用系统硬件提供的Real Time Clock机制,通过读取RTC硬件/dev/rtc,通过ioctl()设置RTC频率,代码如下:

[cpp] view plain copy
  1. #include <stdio.h>  
  2. #include <linux/rtc.h>  
  3. #include <sys/ioctl.h>  
  4. #include <sys/time.h>  
  5. #include <sys/types.h>  
  6. #include <fcntl.h>  
  7. #include <unistd.h>  
  8. #include <errno.h>  
  9. #include <stdlib.h>  
  10.   
  11. int main(int argc, char* argv[])  
  12. {  
  13.         unsigned long i = 0;  
  14.         unsigned long data = 0;  
  15.         int retval = 0;  
  16.         int fd = open ("/dev/rtc", O_RDONLY);  
  17.   
  18.         if(fd < 0)  
  19.         {  
  20.                 perror("open");  
  21.                 exit(errno);  
  22.         }  
  23.   
  24.         /*Set the freq as 4Hz*/  
  25.         if(ioctl(fd, RTC_IRQP_SET, 1) < 0)  
  26.         {  
  27.                 perror("ioctl(RTC_IRQP_SET)");  
  28.                 close(fd);  
  29.                 exit(errno);  
  30.         }  
  31.         /* Enable periodic interrupts */  
  32.         if(ioctl(fd, RTC_PIE_ON, 0) < 0)  
  33.         {  
  34.                 perror("ioctl(RTC_PIE_ON)");  
  35.                 close(fd);  
  36.                 exit(errno);  
  37.         }  
  38.   
  39.         for(i = 0; i < 100; i++)  
  40.         {  
  41.                 if(read(fd, &data, sizeof(unsigned long)) < 0)  
  42.                 {  
  43.                         perror("read");  
  44.                         close(fd);  
  45.                         exit(errno);  
  46.   
  47.                 }  
  48.                 printf("timer\n");  
  49.         }  
  50.         /* Disable periodic interrupts */  
  51.         ioctl(fd, RTC_PIE_OFF, 0);  
  52.         close(fd);  
  53.   
  54.         return 0;  
  55. }  
这种方式比较方便,利用了系统硬件提供的RTC,精度可调,而且非常高。
4,使用select()

这种方法在看APUE神书时候看到的,方法比较冷门,通过使用select(),来设置定时器;原理利用select()方法的第5个参数,第一个参数设置为0,三个文件描述符集都设置为NULL,第5个参数为时间结构体,代码如下:

[cpp] view plain copy
  1. #include <sys/time.h>  
  2. #include <sys/select.h>  
  3. #include <time.h>  
  4. #include <stdio.h>  
  5.   
  6. /*seconds: the seconds; mseconds: the micro seconds*/  
  7. void setTimer(int seconds, int mseconds)  
  8. {  
  9.         struct timeval temp;  
  10.   
  11.         temp.tv_sec = seconds;  
  12.         temp.tv_usec = mseconds;  
  13.   
  14.         select(0, NULL, NULL, NULL, &temp);  
  15.         printf("timer\n");  
  16.   
  17.         return ;  
  18. }  
  19.   
  20. int main()  
  21. {  
  22.         int i;  
  23.   
  24.         for(i = 0 ; i < 100; i++)  
  25.                 setTimer(1, 0);  
  26.   
  27.         return 0;  
  28. }  
这种方法精度能够达到微妙级别,网上有很多基于select()的多线程定时器,说明select()稳定性还是非常好。


总结:如果对系统要求比较低,可以考虑使用简单的sleep(),毕竟一行代码就能解决;如果系统对精度要求比较高,则可以考虑RTC机制和select()机制。

0 0
原创粉丝点击