linux 定时轮训任务实现
#include <stdio.h>
#include <signal.h>
#include <sys/time.h>
int main(int argc, char *argv[])
{
sigset_t block;
struct itimerval itv;
sigemptyset(&block);
sigaddset(&block, SIGALRM);
sigprocmask(SIG_BLOCK, &block, NULL);
itv.it_interval.tv_sec = 2;
itv.it_interval.tv_usec = 0;
itv.it_value = itv.it_interval;
setitimer(ITIMER_REAL, &itv, NULL);
while (1) {
printf("%d\n", time(NULL));
sigwaitinfo(&block, NULL);
}
return 0;
}
进程的间隔计时器能够提供的时间精度为微秒,对于大多数的应用来说,应该已经足够,如果需要更高的时间精度,或者需要多个定时器,那么每个进程一个的实时间隔定时器就无能为力了,这个时候我们可以选择POSIX实时扩展中的定时器:
#include <signal.h>
#include <time.h>
int timer_create(clockid_t clockid, struct sigevent *restrict evp,
timer_t *restrict timerid);
int timer_getoverrun(timer_t timerid);
int timer_gettime(timer_t timerid, struct itimerspec *value);
int timer_settime(timer_t timerid, int flags,
const struct itimerspec *restrict value,
struct itimerspec *restrict ovalue);
它实际上就是进程间隔定时器的增强版,除了可以定制时钟源(nanosleep也存在能定制时钟源的版本:clock_nanosleep)和时间精度提高到纳秒外,它还能通过将evp->sigev_notify设定为如下值来定制定时器到期后的行为:
更新后的程序如下(需要连接实时扩展库: -lrt)
至于时钟源为什么是CLOCK_MONOTONIC而不是CLOCK_REALTIME,主要是考虑到系统的实时时钟可能会在程序运行过程中更改,所以存在一定的不确定性,而CLOCK_MONOTONIC则不会,较为稳定。
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <errno.h>
#include <sched.h>
int main(int argc, char *argv[])
{
timer_t timer;
struct itimerspec timeout;
sigset_t block;
struct sched_param param;
sigemptyset(&block);
sigaddset(&block, SIGALRM);
sigprocmask(SIG_BLOCK, &block, NULL);
timer_create(CLOCK_MONOTONIC, NULL, &timer);
timeout.it_interval.tv_sec = 2;
timeout.it_interval.tv_nsec = 0;
timeout.it_value = timeout.it_interval;
timer_settime(timer, 0, &timeout, NULL);
while (1) {
fprintf(stderr, "%d\n", time(NULL));
sigwaitinfo(&block, NULL);
}
return 0;
}
至此为止,我们已经找到了目前Linux提供的精度最高的定时器API,它应该能满足大多数情况的要求了