【问题标题】:how to set multiple Alarms using "setitimer()" function call如何使用“setitimer()”函数调用设置多个警报
【发布时间】:2017-11-24 10:23:34
【问题描述】:

我需要在同一进程中设置多个间隔计时器(相同类型的警报:ITIMER_REAL)。所以我使用 setitimer() 系统调用来创建 3 个警报,每个计时器都有单独的结构来保存时间间隔值。当任何定时器到期时,它都会向调用进程发出信号 SIGALRM,但我找不到三个定时器中的哪个定时器发出信号,我什至不知道所有定时器是否都在运行。有什么方法可以找到哪个计时器发出了信号... 谢谢。

#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>

void timer_handler (int signum)
{
 static int count = 0;
 printf ("timer1 expired %d times\n", ++count);
}


int main ()
{   
    int m = 0;
     struct sigaction sa;
     struct itimerval timer1, timer2, timer3;

     memset (&sa, 0, sizeof (sa));

     sa.sa_handler = &timer_handler;

     sigaction (SIGALRM/*SIGVTALRM*/, &sa, NULL);

     timer1.it_value.tv_sec = 1;
     timer1.it_value.tv_usec = 0;
     timer1.it_interval.tv_sec = 5;
     timer1.it_interval.tv_usec = 0;

     timer2.it_value.tv_sec = 2;
     timer2.it_value.tv_usec = 0/* 900000*/;
     timer2.it_interval.tv_sec = 5;
     timer2.it_interval.tv_usec = 0/*900000*/;

     timer3.it_value.tv_sec = 3;
     timer3.it_value.tv_usec = 0/* 900000*/;
     timer3.it_interval.tv_sec = 5;
     timer3.it_interval.tv_usec = 0/*900000*/;

     setitimer (ITIMER_REAL/*ITIMER_VIRTUAL*/, &timer1, NULL);
     setitimer (ITIMER_REAL/*ITIMER_VIRTUAL*/, &timer2, NULL);
     setitimer (ITIMER_REAL/*ITIMER_VIRTUAL*/, &timer3, NULL);

    while (1)
    {
        //printf("\nin main  %d",m++);
        //sleep(1);
    }
}

【问题讨论】:

    标签: c linux setitimer


    【解决方案1】:

    不,每个进程只有一个 ITIMER_REAL 计时器。多次使用setitimer会覆盖之前的值,见man setitimer

    一个进程只有三种定时器中的每一种。

    当您修改示例代码中的间隔时,您也可以看到这一点

    timer1.it_interval.tv_sec = 1;
    timer2.it_interval.tv_sec = 2;
    

    并使用nanosleep 而不是sleep,因为它可能会干扰SIGALRM

    现在运行代码,您只会看到 5 秒的时间间隔。


    您还可以通过提供第二个struct itimerval 来检索之前的设置值

    struct itimerval old1, old2, old3;
    setitimer(ITIMER_REAL, &timer1, &old1);
    setitimer(ITIMER_REAL, &timer2, &old2);
    setitimer(ITIMER_REAL, &timer3, &old3);
    

    old1 将包含零值,因为这是您第一次使用setitimerold2 包含 it_interval = 1 secold3 包含 it_interval = 2 secit_values 会有所不同,具体取决于调用 setitimer 之间经过的时间。

    因此,如果您需要多个计时器,则需要进行一些记账。每次计时器到期时,您必须计算下一个计时器并相应地调用setitimer


    作为替代方案,您可以查看POSIX timers。这允许创建多个计时器

    一个程序可以使用 timer_create() 创建多个间隔计时器。

    并通过sigevent 将一些id 传递给处理程序。虽然手册页末尾的 example 看起来有点复杂。

    【讨论】:

      【解决方案2】:

      如果我理解你的问题,你想知道不同计时器的状态。

      在参考中一个 getitimer 函数 avalable:

      函数getitimer()填充curr_value指向的结构 与指定的定时器的当前设置(其中之一 ITIMER_REAL、ITIMER_VIRTUAL 或 ITIMER_PROF)。元素 it_value 是 设置为计时器上剩余的时间量,如果计时器为零,则设置为 被禁用。同样,it_interval 设置为复位值。

      您可以在这里找到完整的参考资料Link

      希望有帮助

      【讨论】:

      • 感谢您的回答,但我的问题是,我可以在同一个进程中创建多个警报计时器吗?如果可以的话,因为所有计时器都会向调用进程发出相同类型的信号它们过期(例如:对于 ITIMER_REAL 类型的所有计时器,引发的信号是 SIGALRM),它必须执行相同的信号处理函数。那么我怎样才能知道哪个定时器已经过期(或者哪个定时器发出了信号),因为根据定时器过期我会进入不同的状态(FSM)。
      • 嘿,我在想的是getitimer()函数。您可以检查所有 3 个计时器,更改其值的那个是最近过期的那个。示例:SIGALARM -> getitimer() of all 3 -> 1, 3 正在运行并且 2 已过期 -> 处理计时器 2 超时。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-13
      • 1970-01-01
      • 2022-09-28
      相关资源
      最近更新 更多