4

我试图让信号处理程序在不退出程序的情况下停止计时器。我该怎么走。我希望 StopTimer 处理停止计时器的信号

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sys/time.h>
#include <signal.h>
#include <unistd.h>

#define INTERVAL 2      // number of seconds to go off

int main(int argc, char* argv[]) {

TimerSet(INTERVAL);

while(1)
{
    // do stuff
}
return 0;
}

void TimerSet(int interval)
{
printf("starting timer\n");
struct itimerval it_val;

// interval value
it_val.it_value.tv_sec = interval;
it_val.it_interval = it_val.it_value;

// on SIGALRM, close window
if (signal(SIGALRM, TimerStop) == SIG_ERR)
{
    perror("Unable to catch SIGALRM");
    exit(1);
}

// set interval timer, returns SIGALRM on expiration
if (setitimer(ITIMER_REAL, &it_val, NULL) == -1)
{
    perror("error calling setitimer()");
    exit(1);
}
}

void TimerStop(int signum)
{
printf("Timer ran out! Stopping timer\n");
exit(signum);
}

我尝试将 setitimer 间隔设置为 0,但我不确定如何在 TimerStop 信号处理函数中使用相同的计时器

4

2 回答 2

4

只需设置it_interval为零,您将获得一个一次性计时器。你不需要在你的处理程序中对它做任何事情。

例如,有了这个:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sys/time.h>
#include <signal.h>
#include <unistd.h>

#define INTERVAL 2              // number of seconds to go off

void TimerStop(int signum) {
    printf("Timer ran out! Stopping timer\n");
}

void TimerSet(int interval) {
    printf("starting timer\n");
    struct itimerval it_val;

    it_val.it_value.tv_sec = interval;
    it_val.it_value.tv_usec = 0;
    it_val.it_interval.tv_sec = 0;
    it_val.it_interval.tv_usec = 0;

    if (signal(SIGALRM, TimerStop) == SIG_ERR) {
        perror("Unable to catch SIGALRM");
        exit(1);
    }
    if (setitimer(ITIMER_REAL, &it_val, NULL) == -1) {
        perror("error calling setitimer()");
        exit(1);
    }
}

int main(int argc, char *argv[]) {

    TimerSet(INTERVAL);

    while (1) {
        // do stuff
    }
    return 0;
}

该消息"Timer ran out! Stopping timer"只会出现一次,并且您的计时器将停止而无需您做任何事情。

请注意,您需要填写您的tv_usec成员struct itimerval,这是您当前的代码不做的。如果您不这样做,it_interval则极不可能为零,并且您的计时器将永远不会停止。

printf()与其他标准 IO 函数一起,从信号处理程序调用并不是真正安全的,尽管在这种特殊情况下它不会给您带来任何问题,因为主代码只是处于循环中而没有做任何事情。

此外,假设您是signal()故意调用 -sigaction()是设置处理程序的推荐方式。setitimer()现在也已经过时了,timer_settime()推荐使用。

于 2013-11-03T22:08:58.947 回答
2

根据手册:

   Timers  decrement  from  it_value  to zero, generate a signal, and reset to
   it_interval.  A timer which is set to zero (it_value is zero or  the  timer
   expires and it_interval is zero) stops.

   Both  tv_sec  and  tv_usec are significant in determining the duration of a
   timer.

因此,如果在 setitimer() 调用之前将时间间隔设置为零,则可以将计时器设置为仅运行一次(感谢 Duck 的评论)。

于 2013-11-03T21:23:10.763 回答