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设定为如下值来定制定时器到期后的行为:
- 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返回的实际线程号,并且这个线程必须实际存在且属于当前的调用进程。
|
至此为止,我们已经找到了目前Linux提供的精度最高的定时器API,它应该能满足大多数情况的要求了