getitimer(2) - Linux 手册页
名称
getitimer, 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);
描述
系统为每个进程提供三个间隔定时器,每个定时器在不同的时间域内递减。当任何定时器到期时,会向该进程发送一个信号,并且定时器(可能)会重新启动。
- ITIMER_REAL
在实时递减,并在到期时发送 SIGALRM。
ITIMER_VIRTUAL
仅当进程正在执行时才递减,并在到期时发送 SIGVTALRM。
ITIMER_PROF
当进程执行时和系统代表进程执行时都递减。与 ITIMER_VIRTUAL 结合使用,此定时器通常用于分析应用程序在用户空间和内核空间中花费的时间。到期时会发送 SIGPROF。
- 定时器的值由以下结构定义
-
struct itimerval { struct timeval it_interval; /* next value */ struct timeval it_value; /* current value */ }; struct timeval { time_t tv_sec; /* seconds */ suseconds_t tv_usec; /* microseconds */ }; - 函数 getitimer() 将指向 curr_value 的结构填充为由 which(ITIMER_REAL、ITIMER_VIRTUAL 或 ITIMER_PROF 的其中之一)指定的定时器的当前设置。元素 it_value 设置为定时器剩余的时间量,或者如果定时器被禁用则设置为零。类似地,it_interval 设置为重置值。
函数 setitimer() 将指定的定时器设置为 new_value 中的值。如果 old_value 非 NULL,则定时器的旧值将存储在那里。
定时器从 it_value 递减到零,生成一个信号,并重置为 it_interval。设置为零的定时器(it_value 为零或定时器到期且 it_interval 为零)将停止。
tv_sec 和 tv_usec 在确定定时器的持续时间方面都具有意义。
定时器绝不会在请求的时间之前到期,但可能会在之后的一小段时间(取决于系统定时器分辨率和系统负载)到期;请参阅 time(7)。(但请参阅下面的 BUG。) 到期时,将生成一个信号并重置定时器。如果定时器在进程活动时到期(对于 ITIMER_VIRTUAL 始终为真),则该信号将在生成时立即传递。否则,传递将延迟一小段时间,具体取决于系统负载。
返回值
成功时返回零。出错时返回 -1,并相应地设置 errno。
错误
- EFAULT
new_value、old_value 或 curr_value 不是有效的指针。
EINVAL
which 不是 ITIMER_REAL、ITIMER_VIRTUAL 或 ITIMER_PROF 的其中之一;或者(从 Linux 2.6.22 开始),指向 new_value 的结构中的 tv_usec 字段包含一个超出 0 到 999999 范围的值。
符合
POSIX.1-2001, SVr4, 4.4BSD (此调用首次出现在 4.2BSD 中)。POSIX.1-2008 将 getitimer() 和 setitimer() 标记为已弃用,建议使用 POSIX 定时器 API (timer_gettime(2), timer_settime(2) 等) 代替。
说明
通过 fork(2) 创建的子进程不会继承其父进程的间隔定时器。间隔定时器在 execve(2) 期间保留。
POSIX.1 未指定 setitimer() 与三个接口 alarm(2), sleep(3) 和 usleep(3) 之间的交互。
标准对以下调用的含义保持沉默
setitimer(which, NULL, &old_value);
许多系统 (Solaris, BSDs, 也许还有其他系统) 将其视为等同于
getitimer(which, &old_value);
在 Linux 中,这被视为等同于一个调用,其中 new_value 字段为零;也就是说,定时器被禁用。不要使用这个 Linux 的错误特性:它不可移植且不必要。
错误
信号的生成和传递是不同的,并且对于进程,上述信号中的每个信号只能有一个实例处于挂起状态。在极高的负载下,ITIMER_REAL 定时器可能会在先前到期的信号被传递之前到期。在这种情况下,第二个信号将会丢失。
在 Linux 内核 2.6.16 之前的版本上,定时器的值以 jiffies 为单位表示。如果请求设置一个定时器,其 jiffies 表示形式超过 MAX_SEC_IN_JIFFIES(在 include/linux/jiffies.h 中定义),则定时器将被无声地截断到该上限值。在 Linux/i386 上(自 Linux 2.6.13 以来,默认 jiffy 为 0.004 秒),这意味着定时器的上限值约为 99.42 天。从 Linux 2.6.16 开始,内核使用不同的内部表示形式来表示时间,并且删除了此上限。
在某些系统(包括 i386)上,Linux 内核版本 2.6.12 之前存在一个错误,在某些情况下会导致定时器过早到期,最多提前一个 jiffy。此错误已在内核 2.6.12 中修复。
POSIX.1-2001 规定,如果指定了超出 0 到 999999 范围的 tv_usec 值,则 setitimer() 应该失败。但是,在内核高达并包括 2.6.21 的版本中,Linux 不会报错,而是会静默地调整定时器相应的秒数值。从内核 2.6.22 开始,此不符合规范的情况已得到修复:不正确的 tv_usec 值将导致 EINVAL 错误。
参见
gettimeofday(2), sigaction(2), signal(2), timer_create(2), timerfd_create(2), time(7)