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

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

1,使用sleep()和usleep()

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

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

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

 

 
  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频率,代码如下:

 

 
  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个参数为时间结构体,代码如下:

 

 
  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
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值