作者:zhanhailiang 日期:2014-10-25

原理

Linux为每个进程提供3种定时器:

  1. ITIMER_REAL: 以系统真实的时间来计算,它送出SIGALRM信号。
  2. ITIMER_VIRTUAL: 以该进程在用户态下花费的时间来计算,它送出SIGVTALRM信号。
  3. ITIMER_PROF: 以该进程在用户态下和内核态下所费的时间来计算,它送出SIGPROF信号。

其通过setitimer来初始化:

<span class="kw4" style="color: rgb(153, 51, 51);">int</span> sigaction<span class="br0" style="color: rgb(102, 204, 102);">(</span><span class="kw4" style="color: rgb(153, 51, 51);">int</span> signum<span class="sy0" style="color: rgb(102, 204, 102);">,</span><span class="kw4" style="color: rgb(153, 51, 51);">const</span> <span class="kw4" style="color: rgb(153, 51, 51);">struct</span> sigaction <span class="sy0" style="color: rgb(102, 204, 102);">*</span>act <span class="sy0" style="color: rgb(102, 204, 102);">,</span><span class="kw4" style="color: rgb(153, 51, 51);">struct</span> sigaction <span class="sy0" style="color: rgb(102, 204, 102);">*</span>oldact<span class="br0" style="color: rgb(102, 204, 102);">)</span><span class="sy0" style="color: rgb(102, 204, 102);">;</span>

设置定时器后在当前进程终止前每隔固定时间都会发送相应的信号。

此时我们通过sigaction来接收相应信号并处理相应逻辑:

<span class="kw4" style="color: rgb(153, 51, 51);">int</span> sigaction<span class="br0" style="color: rgb(102, 204, 102);">(</span><span class="kw4" style="color: rgb(153, 51, 51);">int</span> signum<span class="sy0" style="color: rgb(102, 204, 102);">,</span><span class="kw4" style="color: rgb(153, 51, 51);">const</span> <span class="kw4" style="color: rgb(153, 51, 51);">struct</span> sigaction <span class="sy0" style="color: rgb(102, 204, 102);">*</span>act <span class="sy0" style="color: rgb(102, 204, 102);">,</span><span class="kw4" style="color: rgb(153, 51, 51);">struct</span> sigaction <span class="sy0" style="color: rgb(102, 204, 102);">*</span>oldact<span class="br0" style="color: rgb(102, 204, 102);">)</span><span class="sy0" style="color: rgb(102, 204, 102);">;</span>

Demo

如下举例说明如何使用Linux定时器定时输出一段文本:

<span class="co2" style="color: rgb(51, 153, 51);">#include <sys/time.h></span>
<span class="co2" style="color: rgb(51, 153, 51);">#include <stdio.h></span>
<span class="co2" style="color: rgb(51, 153, 51);">#include <stdlib.h></span>
<span class="co2" style="color: rgb(51, 153, 51);">#include <unistd.h></span>
<span class="co2" style="color: rgb(51, 153, 51);">#include <signal.h></span>
<span class="co2" style="color: rgb(51, 153, 51);">#include <string.h></span>
 
<span class="co2" style="color: rgb(51, 153, 51);">#define PROMPT "2 seconds over\n\a"</span>
 
<span class="kw4" style="color: rgb(153, 51, 51);">char</span> <span class="sy0" style="color: rgb(102, 204, 102);">*</span>prompt <span class="sy0" style="color: rgb(102, 204, 102);">=</span> PROMPT<span class="sy0" style="color: rgb(102, 204, 102);">;</span>
<span class="kw4" style="color: rgb(153, 51, 51);">unsigned</span> <span class="kw4" style="color: rgb(153, 51, 51);">int</span> len<span class="sy0" style="color: rgb(102, 204, 102);">;</span>
 
<span class="kw4" style="color: rgb(153, 51, 51);">void</span> prompt_info <span class="br0" style="color: rgb(102, 204, 102);">(</span><span class="kw4" style="color: rgb(153, 51, 51);">int</span> signo<span class="br0" style="color: rgb(102, 204, 102);">)</span> <span class="br0" style="color: rgb(102, 204, 102);">{</span>
    write <span class="br0" style="color: rgb(102, 204, 102);">(</span>STDERR_FILENO<span class="sy0" style="color: rgb(102, 204, 102);">,</span> prompt<span class="sy0" style="color: rgb(102, 204, 102);">,</span> len<span class="br0" style="color: rgb(102, 204, 102);">)</span><span class="sy0" style="color: rgb(102, 204, 102);">;</span>
<span class="br0" style="color: rgb(102, 204, 102);">}</span>
 
<span class="coMULTI" style="color: rgb(128, 128, 128); font-style: italic;">/*
 * 设置收到SIGPROF信号的处理方式为prompt_info,打印一段文本
 */</span>
<span class="kw4" style="color: rgb(153, 51, 51);">void</span> init_sigaction <span class="br0" style="color: rgb(102, 204, 102);">(</span><span class="kw4" style="color: rgb(153, 51, 51);">void</span><span class="br0" style="color: rgb(102, 204, 102);">)</span> <span class="br0" style="color: rgb(102, 204, 102);">{</span>
    <span class="kw4" style="color: rgb(153, 51, 51);">struct</span> sigaction act<span class="sy0" style="color: rgb(102, 204, 102);">;</span>
    act.<span class="me1" style="color: rgb(0, 102, 0);">sa_handler</span> <span class="sy0" style="color: rgb(102, 204, 102);">=</span> prompt_info<span class="sy0" style="color: rgb(102, 204, 102);">;</span>
    act.<span class="me1" style="color: rgb(0, 102, 0);">sa_flags</span> <span class="sy0" style="color: rgb(102, 204, 102);">=</span> <span class="nu0" style="color: rgb(204, 102, 204);">0</span><span class="sy0" style="color: rgb(102, 204, 102);">;</span>
    sigemptyset <span class="br0" style="color: rgb(102, 204, 102);">(</span><span class="sy0" style="color: rgb(102, 204, 102);">&</span>act.<span class="me1" style="color: rgb(0, 102, 0);">sa_mask</span><span class="br0" style="color: rgb(102, 204, 102);">)</span><span class="sy0" style="color: rgb(102, 204, 102);">;</span>
    sigaction <span class="br0" style="color: rgb(102, 204, 102);">(</span>SIGPROF<span class="sy0" style="color: rgb(102, 204, 102);">,</span> <span class="sy0" style="color: rgb(102, 204, 102);">&</span>act<span class="sy0" style="color: rgb(102, 204, 102);">,</span> NULL<span class="br0" style="color: rgb(102, 204, 102);">)</span><span class="sy0" style="color: rgb(102, 204, 102);">;</span>
<span class="br0" style="color: rgb(102, 204, 102);">}</span>
 
<span class="coMULTI" style="color: rgb(128, 128, 128); font-style: italic;">/*
 * 设置ITIMER_PROF类型的定时器, 每隔2秒发送一次SIGPROF信号
 */</span>
<span class="kw4" style="color: rgb(153, 51, 51);">void</span> init_time <span class="br0" style="color: rgb(102, 204, 102);">(</span><span class="br0" style="color: rgb(102, 204, 102);">)</span> <span class="br0" style="color: rgb(102, 204, 102);">{</span>
    <span class="kw4" style="color: rgb(153, 51, 51);">struct</span> itimerval value<span class="sy0" style="color: rgb(102, 204, 102);">;</span>
    value.<span class="me1" style="color: rgb(0, 102, 0);">it_value</span>.<span class="me1" style="color: rgb(0, 102, 0);">tv_sec</span> <span class="sy0" style="color: rgb(102, 204, 102);">=</span> <span class="nu0" style="color: rgb(204, 102, 204);">2</span><span class="sy0" style="color: rgb(102, 204, 102);">;</span>
    value.<span class="me1" style="color: rgb(0, 102, 0);">it_value</span>.<span class="me1" style="color: rgb(0, 102, 0);">tv_usec</span> <span class="sy0" style="color: rgb(102, 204, 102);">=</span> <span class="nu0" style="color: rgb(204, 102, 204);">0</span><span class="sy0" style="color: rgb(102, 204, 102);">;</span>
    value.<span class="me1" style="color: rgb(0, 102, 0);">it_interval</span> <span class="sy0" style="color: rgb(102, 204, 102);">=</span> value.<span class="me1" style="color: rgb(0, 102, 0);">it_value</span><span class="sy0" style="color: rgb(102, 204, 102);">;</span>
    setitimer <span class="br0" style="color: rgb(102, 204, 102);">(</span>ITIMER_PROF<span class="sy0" style="color: rgb(102, 204, 102);">,</span> <span class="sy0" style="color: rgb(102, 204, 102);">&</span>value<span class="sy0" style="color: rgb(102, 204, 102);">,</span> NULL<span class="br0" style="color: rgb(102, 204, 102);">)</span><span class="sy0" style="color: rgb(102, 204, 102);">;</span>
<span class="br0" style="color: rgb(102, 204, 102);">}</span>
 
<span class="kw4" style="color: rgb(153, 51, 51);">int</span> main <span class="br0" style="color: rgb(102, 204, 102);">(</span><span class="br0" style="color: rgb(102, 204, 102);">)</span> <span class="br0" style="color: rgb(102, 204, 102);">{</span>
    len <span class="sy0" style="color: rgb(102, 204, 102);">=</span> <a target=_blank target="_blank" href="http://www.opengroup.org/onlinepubs/009695399/functions/strlen.html" style="color: rgb(43, 115, 183); text-decoration: none; outline: none;"><span class="kw3" style="color: rgb(0, 0, 102);">strlen</span></a> <span class="br0" style="color: rgb(102, 204, 102);">(</span>prompt<span class="br0" style="color: rgb(102, 204, 102);">)</span><span class="sy0" style="color: rgb(102, 204, 102);">;</span>
    init_sigaction <span class="br0" style="color: rgb(102, 204, 102);">(</span><span class="br0" style="color: rgb(102, 204, 102);">)</span><span class="sy0" style="color: rgb(102, 204, 102);">;</span>
    init_time <span class="br0" style="color: rgb(102, 204, 102);">(</span><span class="br0" style="color: rgb(102, 204, 102);">)</span><span class="sy0" style="color: rgb(102, 204, 102);">;</span>
    <span class="kw1" style="color: rgb(177, 177, 0);">while</span> <span class="br0" style="color: rgb(102, 204, 102);">(</span><span class="nu0" style="color: rgb(204, 102, 204);">1</span><span class="br0" style="color: rgb(102, 204, 102);">)</span><span class="sy0" style="color: rgb(102, 204, 102);">;</span>
    <a target=_blank target="_blank" href="http://www.opengroup.org/onlinepubs/009695399/functions/exit.html" style="color: rgb(43, 115, 183); text-decoration: none; outline: none;"><span class="kw3" style="color: rgb(0, 0, 102);">exit</span></a> <span class="br0" style="color: rgb(102, 204, 102);">(</span><span class="nu0" style="color: rgb(204, 102, 204);">0</span><span class="br0" style="color: rgb(102, 204, 102);">)</span><span class="sy0" style="color: rgb(102, 204, 102);">;</span>
<span class="br0" style="color: rgb(102, 204, 102);">}</span>

编译执行如下:

<span class="br0" style="color: rgb(102, 204, 102);">[</span>root<span class="sy0" style="color: rgb(102, 204, 102);">@</span>~<span class="sy0" style="color: rgb(102, 204, 102);">/</span>wade<span class="sy0" style="color: rgb(102, 204, 102);">/</span>codeReview<span class="sy0" style="color: rgb(102, 204, 102);">/</span>learningc<span class="sy0" style="color: rgb(102, 204, 102);">/</span><span class="nu0" style="color: rgb(204, 102, 204);">10</span><span class="br0" style="color: rgb(102, 204, 102);">]</span><span class="co0" style="color: rgb(102, 102, 102); font-style: italic;"># gcc interval.c -o interval</span>
<span class="br0" style="color: rgb(102, 204, 102);">[</span>root<span class="sy0" style="color: rgb(102, 204, 102);">@</span>~<span class="sy0" style="color: rgb(102, 204, 102);">/</span>wade<span class="sy0" style="color: rgb(102, 204, 102);">/</span>codeReview<span class="sy0" style="color: rgb(102, 204, 102);">/</span>learningc<span class="sy0" style="color: rgb(102, 204, 102);">/</span><span class="nu0" style="color: rgb(204, 102, 204);">10</span><span class="br0" style="color: rgb(102, 204, 102);">]</span><span class="co0" style="color: rgb(102, 102, 102); font-style: italic;"># ./interval </span>
<span class="nu0" style="color: rgb(204, 102, 204);">2</span> seconds over
<span class="nu0" style="color: rgb(204, 102, 204);">2</span> seconds over
<span class="nu0" style="color: rgb(204, 102, 204);">2</span> seconds over
<span class="nu0" style="color: rgb(204, 102, 204);">2</span> seconds over
<span class="nu0" style="color: rgb(204, 102, 204);">2</span> seconds over
^C
<span class="br0" style="color: rgb(102, 204, 102);">[</span>root<span class="sy0" style="color: rgb(102, 204, 102);">@</span>~<span class="sy0" style="color: rgb(102, 204, 102);">/</span>wade<span class="sy0" style="color: rgb(102, 204, 102);">/</span>codeReview<span class="sy0" style="color: rgb(102, 204, 102);">/</span>learningc<span class="sy0" style="color: rgb(102, 204, 102);">/</span><span class="nu0" style="color: rgb(204, 102, 204);">10</span><span class="br0" style="color: rgb(102, 204, 102);">]</span><span class="co0" style="color: rgb(102, 102, 102); font-style: italic;"># </span>

参考阅读