关于Linux应用层的定时器

1.什么是定时器

定时器,顾名思义就是用来定时的,通俗的可以将其看作一个闹钟。在Linux应用编程层上,当需要实现下列几种功能时,可考虑使用定时器。

  • 1.周期性执行某一项任务;
  • 2.在指定时间去执行某一项任务;

2.为什么使用定时器

当有上诉功能需要实现时,不使用定时器的情况下,可使用gettimeofday、difftime 等自己来计算时间间隔(使用系统时基),然后时间到了就执行某一任务,但是这种方法效率低,一般不推荐;

3.如何使用定时器

在学习如何使用定时器之前,我们先来了解下在Linux应用层上有哪些定时器可供使用,各有何优缺点。

一、具有定时功能的库函数API接口:

1.sleep()
2.usleep()
3.nanosleep()
4.alarm()

sleep和usleep,Linux并没有提供系统调用,他们都是在库函数中实现的;是通过调用alarm()来设定报警时间,调用sigsuspend()将进程挂起在信号SIGALARM上。(如果不忽略或不捕捉该信号,该进程会被终止???)sleep精度是1秒,usleep精度是1微妙;使用这种方法缺点比较明显,在Linux系统中,sleep类函数不能保证精度,尤其在系统负载比较大时,一般都会有超时现象。
nanosleep()则是Linux中的系统调用,它是使用定时器来实现的,该调用使调用进程睡眠;
alarm()也是通过定时器实现的,其精度只精确到秒级,它设置的定时器执行函数是在指定时间向当前进程发送SIGALRM信号;

二、进程间隔定时器itimer

所谓“间隔定时器(Interval Timer,简称itimer)就是指定时器采用“间隔”值(interval)来作为计时方式,当定时器启动后,间隔值interval将不断减小。当interval值减到0时,我们就说该间隔定时器到期。
间隔定时器主要被应用在用户进程上。每个Linux进程都有三个相互关联的间隔定时器:

  • 真实间隔定时器(ITIMER_REAL-以系统真实的时间计算):这种间隔定时器在启动后,不管进程是否运行,每个时钟滴答都将其间隔计数器减1。当减到0值时,内核向进程发送SIGALRM信号。
  • 虚拟间隔定时器(ITIMER_VIRT-以该进程在用户态下花费的时间来计算):也称为进程的用户态间隔定时器。当虚拟间隔定时器启动后,只有当进程在用户态下运行时,一次时钟滴答才能使间隔计数器当前值it_virt_value减1。当减到0值时,内核向进程发送SIGVTALRM信号(虚拟闹钟信号),并将it_virt_value重置为初值it_virt_incr。
  • PROF间隔定时器(ITIMER_PROF-以该进程在用户态下和内核态下所费的时间来计算):当一个进程的PROF间隔定时器启动后,则只要该进程处于运行中,而不管是在用户态或核心态下执行,每个时钟滴答都使间隔计数器it_prof_value值减1。当减到0值时,内核向进程发送SIGPROF信号,并将it_prof_value重置为初值it_prof_incr。
三、POSIX定时器

POSIX定时器的是为了解决间隔定时器itimer的以下问题:

  • 一个进程同一时刻只能有一个同一种类型(ITIMER_REAL, ITIMER_PROF, ITIMER_VIRT)的itimer。POSIX定时器在一个进程中可以创建任意多个timer。
  • itimer定时器到期后,只能通过信号(SIGALRM,SIGVTALRM,SIGPROF)的方式通知进程,POSIX定时器到期后不仅可以通过信号进行通知,还可以使用自定义信号,还可以通过启动一个线程来进行通知。
  • itimer支持us级别,POSIX定时器支持ns级别。

号称最强大的定时器接口来自POSIX时钟系列。

四、自定义定时器实现

使用select()
使用gettimeofday、difftime

需要注意,当系统中的一个模块需要频繁的获取系统时间,使用linux中内置的函数开销过大,使用gettimeofday做定时器的弊端也就呈现。

4.总结

在业务项目中,对于系统提供的定时器API往往很难满足我们的需求:
函数alarm本质上设置的是低精确、非重载的ITIMER_REAL类定时器,它只能精确到秒,并且每次设置只能产生一次定时。函数setitimer 设置的定时器则不同,它们不但可以计时到微妙(理论上),还能自动循环定时。在一个Unix进程中,不能同时使用alarm和ITIMER_REAL类定时器。

itimer在进程中每种timer类型(ITIMER_REAL, ITIMER_PROF, ITIMER_VIRT)只能使用一个,另外一点就是他是基于signal进行超时提醒,不仅和alarm,sleep这些api冲突,而且在业务代码中signal是个很不可控的机制,尽量减少使用。

POSIX定时器在itimer基础上进行了很大的改进,解决了itimer的不足,可以说POSIX定时器可以满足了业务很多的需求。

下一节,我们将具体介绍POSIX定时器。

你可能感兴趣的:(关于Linux应用层的定时器)