#include
#include
#include
intmain(intargc,char*argv[])
{
sigset_t block;
structitimervalitv;
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);
}
return0;
}
进程的间隔计时器能够提供的时间精度为微秒,对于大多数的应用来说,应该已经足够,如果需要更高的时间精度,或者需要多个定时器,那么每个进程一个的实时间隔定时器就无能为力了,这个时候我们可以选择POSIX实时扩展中的定时器:
#include
#include
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设定为如下值来定制定时器到期后的行为:
SIGEV_SIGNAL: 发送由evp->sigev_sino指定的信号到调用进程,evp->sigev_value的值将被作为siginfo_t结构体中si_value的值。
SIGEV_NONE:什么都不做,只提供通过timer_gettime和timer_getoverrun查询超时信息。
SIGEV_THREAD: 以evp->sigev_notification_attributes为线程属性创建一个线程,在新建的线程内部以evp->sigev_value为参数调用evp->sigev_notification_function。
SIGEV_THREAD_ID:和SIGEV_SIGNAL类似,不过它只将信号发送到线程号为evp->sigev_notify_thread_id的线程,注意:这里的线程号不一定是POSIX线程号,而是线程调用gettid返回的实际线程号,并且这个线程必须实际存在且属于当前的调用进程。
更新后的程序如下(需要连接实时扩展库: -lrt)
#include
#include
#include
#include
#include
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;
}
至于时钟源为什么是CLOCK_MONOTONIC而不是CLOCK_REALTIME,主要是考虑到系统的实时时钟可能会在程序运行过程中更改,所以存在一定的不确定性,而CLOCK_MONOTONIC则不会,较为稳定。
至此为止,我们已经找到了目前Linux提供的精度最高的定时器API,它应该能满足大多数情况的要求了