概述
alarm
alarm会设置一个定时器,当时间到期后会触发SIGALRM信号,该信号可能会打断系统调用的执行,它使用的定时器和setitimer对应的ITIMER_REAL是同一个。
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <string.h>
#include "include/debug.h"
void sig_func(int signo)
{
pr_info("SIGALRM received!n");
}
int set_signal(int signo, void func(int signo))
{
struct sigaction act, oact;
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
#ifdef SA_INTERRUPT
act.sa_flags |= SA_INTERRUPT;
#endif
if (sigaction(signo, &act, &oact) < 0) {
printf("sigaction error,%sn",strerror(errno));
return 1;
}
return 0;
}
int main()
{
char buf[10];
int fd;
set_signal(SIGALRM, sig_func);
alarm(5);
pr_info("block readn");
read(STDIN_FILENO, buf, 10);
pr_info("read returnsn");
return 0;
}
运行结果:
$ ./timer_test
[6858] INFO: block read
[6858] INFO: SIGALRM received!
[6858] INFO: read returns
alarm会打断阻塞的系统调用,因此使用时要注意处理errno。
setitimer
#include <sys/time.h>
int getitimer(int which, struct itimerval *curr_value);
int setitimer(int which, const struct itimerval *new_value,
struct itimerval *old_value);
setitimer根据参数的不同可能会产生三种不同的信号:
ITIMER_REAL 到期产生SIGALRM信号
ITIMER_VIRTUAL 到期产生SIGVTALRM信号
ITIMER_PROF 到期产生SIGPROF信号
既然会产生信号,同样不可避免的会打断阻塞的系统调用。
alarm和setitimer的关系
当setitimer设置参数ITIMER_REAL时产生的是SIGALRM信号,并且使用的定时器也属于同一个,因此如果和alarm共用可能会产生意象不到的结果,因此要慎重。
posix timer API
setitimer限定每个进程只能设置一个定时器,对于多个定时任务,只能自己实现一个timer链表去处理,对于需要多个定时任务的进程不太友好。
posix timer API允许一个进程可以创建很多个定时器任务,这是它的一大优势:
timer_create: 创建了一个定时器。
timer_settime: 启动或者停止一个定时器。
timer_gettime: 返回到下一次到期的剩余时间值。
timer_getoverrun: 返回上次定时器到期时超限值。
timer_delete: 停止并删除一个定时器。
timer的触发方式也比较灵活,可以选择上报signal,也可以选择运行一个thread function,具体参见man手册。clockid为:
CLOCK_REALTIME
CLOCK_MONOTONIC
CLOCK_PROCESS_CPUTIME_ID
CLOCK_THREAD_CPUTIME_ID
alarm timer
上面介绍的timer都是跟随系统tick进行计算时间的,当系统处于休眠状态时,这些tick都会停掉,因此定时器也会失效,此时如果想要定时器继续工作,就必须使用alarm timer。
Linux系统中有两个时钟可以在系统休眠时继续运行,realtime alarm和boottime alarm。alarm timer借助RTC设备,一直供电且具备唤醒功能,在系统进入suspend过程中,将最近一次超时时间写入RTC设备,超时后会唤醒系统执行timer超时函数。
想要使用这两个alarm timer,依然可以使用posix timer API。
对应的clockid为:
CLOCK_REALTIME_ALARM
CLOCK_BOOTTIME_ALARM
最后
以上就是香蕉发卡为你收集整理的Linux应用层定时器的全部内容,希望文章能够帮你解决Linux应用层定时器所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复