一、定时器操作
Linux 为每一个进程提供了 3 个 setitimer 间隔计时器:
1. ITIMER_REAL:减少实际时间,到期的时候发出 SIGALRM 信号。
2. ITIMER_VIRTUAL:减少有效时间 (进程执行的时间),产生 SIGVTALRM 信号。
3. ITIMER_PROF:减少进程的有效时间和系统时间 (为进程调度用的时间)。这个经常和上面一个使用用来计算系统内核时间和用户时间。产生 SIGPROF 信号。
所谓 REAL 时间,即我们人类自然感受的时间,英文计算机文档中也经常使用 wall-clock 这个术语。说白了就是我们通常所说的时间,比如现在是下午 5 点 10 分,那么一分钟的 REAL 时间之后就是下午 5 点 11 分。
VIRTUAL 时间是进程执行的时间,Linux 是一个多用户多任务系统,在过去的 1 分钟内,指定进程实际在 CPU 上的执行时间往往并没有 1 分钟,因为其他进程会被 Linux 调度执行,在那些时间内,虽然自然时间在流逝,但指定进程并没有真正的运行。VIRTUAL 时间就是指定进程真正的有效执行时间。比如 5 点 10 分开始的 1 分钟内,进程 P1 被 Linux 调度并占用 CPU 的执行时间为 30 秒,那么VIRTUAL 时间对于进程 P1 来讲就是 30 秒。此时自然时间已经到了 5 点 11 分,但从进程 P1 的眼中看来,时间只过了 30 秒。
PROF 时间比较独特,对进程 P1 来说从 5 点 10 分开始的 1 分钟内,虽然自己的执行时间为 30 秒,但实际上还有 10 秒钟内核是在执行 P1 发起的系统调用,那么这 10 秒钟也被加入到 PROF 时间。这种时间定义主要用于全面衡量进程的性能,因为在统计程序性能的时候,10 秒的系统调用时间也应该算到 P1 的头上。这也许就是 PROF 这个名字的来历吧。
取值 |
含义 |
信号发送 |
ITIMER_REAL |
定时真实时间,与alarm类型相同。 |
SIGALRM |
ITIMER_VIRT |
定时进程在用户态下的实际执行时间。 |
SIGVTALRM |
ITIMER_PROF |
定时进程在用户态和核心态下 |
SIGPROF |
定时器用到的结构:
1 /* Type of the second argument to `getitimer‘ and
2 the second and third arguments `setitimer‘. */
3 struct itimerval
4 {
5 /* Value to put into `it_value‘ when the timer expires. */
6 struct timeval it_interval;
7 /* Time to the next timer expiration. */
8 struct timeval it_value;
9 };
10
11 /* A time value that is accurate to the nearest
12 microsecond but also has a range of years. */
13 struct timeval
14 {
15 __time_t tv_sec; /* Seconds. */
16 __suseconds_t tv_usec; /* Microseconds. */
17 };
函数
1 typedef int __itimer_which_t;
2
3 /* Set *VALUE to the current setting of timer WHICH.
4 Return 0 on success, -1 on errors. */
5 extern int getitimer (__itimer_which_t __which,
6 struct itimerval *__value) __THROW;
7
8 /* Set the timer WHICH to *NEW. If OLD is not NULL,
9 set *OLD to the old value of timer WHICH.
10 Returns 0 on success, -1 on errors. */
11 extern int setitimer (__itimer_which_t __which,
12 const struct itimerval *__restrict __new,
13 struct itimerval *__restrict __old) __THROW;
二、信号操作
这里只介绍与定时器相关的操作,具体信号方面的知识,参见《linux中的进程与信号》一文。
1 /* Get and/or set the action for signal SIG. */ 2 extern int sigaction (int __sig, const struct sigaction *__restrict __act, 3 struct sigaction *__restrict __oact) __THROW; 4 5 /* Structure describing the action to be taken when a signal arrives. */ 6 struct sigaction 7 { 8 /* Signal handler. */ 9 #ifdef __USE_POSIX199309 10 union 11 { 12 /* Used if SA_SIGINFO is not set. */ 13 __sighandler_t sa_handler; 14 /* Used if SA_SIGINFO is set. */ 15 void (*sa_sigaction) (int, siginfo_t *, void *); 16 } 17 __sigaction_handler; 18 # define sa_handler __sigaction_handler.sa_handler 19 # define sa_sigaction __sigaction_handler.sa_sigaction 20 #else 21 __sighandler_t sa_handler; 22 #endif 23 24 /* Additional set of signals to be blocked. */ 25 __sigset_t sa_mask; 26 27 /* Special flags. */ 28 int sa_flags; 29 30 /* Restore handler. */ 31 void (*sa_restorer) (void); 32 };
三、程序例子
1 #include <stdlib.h> 2 #include <signal.h> 3 #include <stdio.h> 4 #include <unistd.h> 5 #include <time.h> 6 #include <sys/time.h> 7 8 void adc_read() 9 { 10 printf("Hello\n"); 11 } 12 13 int main() 14 { 15 struct sigaction act; 16 struct itimerval adc_timer; 17 18 act.sa_handler = adc_read; 19 sigemptyset(&act.sa_mask); 20 act.sa_flags = 0; 21 sigaction(SIGALRM, &act, NULL); 22 23 adc_timer.it_value.tv_sec = 20; 24 adc_timer.it_value.tv_usec = 0; 25 adc_timer.it_interval = adc_timer.it_value; 26 /* 27 * Initialize the timer. 28 * Send SIGALRM signal 29 */ 30 setitimer(ITIMER_REAL, &adc_timer, NULL); 31 while(1); 32 }
除例子外代码来自glibc-2.18