需要说明在 GNU C 中使用 settimer 和 alarm 功能的程序

Posted

技术标签:

【中文标题】需要说明在 GNU C 中使用 settimer 和 alarm 功能的程序【英文标题】:need programs that illustrate use of settimer and alarm functions in GNU C 【发布时间】:2010-01-18 13:01:27 【问题描述】:

谁能用一些程序示例来说明gnu C中settimer或alarm函数的使用?

我有一个持续处理一些数据的程序,我需要设置一个每隔 t 秒响一次的计时器/警报,作为响应,我需要将处理后的数据存储到一个文件中。该文件写入必须是异步的。我浏览了 GNU C 库页面,但我不能理解太多..

[编辑]

我得到了这个程序:

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

#define INTERVAL 1

int howmany = 0;

void alarm_wakeup (int i)

   struct itimerval tout_val;

   signal(SIGALRM,alarm_wakeup);

   howmany += INTERVAL;

   printf("\n%d sec up partner, Wakeup!!!\n",howmany);
   tout_val.it_interval.tv_sec = 0;
   tout_val.it_interval.tv_usec = 0;
   tout_val.it_value.tv_sec = INTERVAL; /* 10 seconds timer */
   tout_val.it_value.tv_usec = 0;

   setitimer(ITIMER_REAL, &tout_val,0);



void exit_func (int i)

    signal(SIGINT,exit_func);
    printf("\nBye Bye!!!\n");
    exit(0);


int main ()

  struct itimerval tout_val;

  tout_val.it_interval.tv_sec = 0;
  tout_val.it_interval.tv_usec = 0;
  tout_val.it_value.tv_sec = INTERVAL; /* 10 seconds timer */
  tout_val.it_value.tv_usec = 0;
  setitimer(ITIMER_REAL, &tout_val,0);

  signal(SIGALRM,alarm_wakeup); /* set the Alarm signal capture */
  signal(SIGINT,exit_func);

  while (1)
  
    //printf("!");
  

  return 0;


但似乎我在计时器开启时​​无能为力.. 我应该修改什么以满足我的需要?请建议.. [/编辑]

【问题讨论】:

【参考方案1】:

这是来自here 的示例,它使用setitimer() 定期调用DoStuff()

这里的关键是调用setitimer() 会导致操作系统调度SIGALRM 在指定时间过去后发送到您的进程,并且由您的程序在该信号到来时处理该信号。您可以通过为信号类型(在本例中为DoStufF())注册一个信号处理函数来处理信号,之后操作系统将知道在计时器到期时调用该函数。

您可以阅读setitimer() man page 以了解参数是什么以及如何取消计时器。

注意:如果您希望计时器只触发一次,则必须调用alarm()ualarm() 而不是setitimer()

/*
 * setitimer.c - simple use of the interval timer
 */

#include <sys/time.h>       /* for setitimer */
#include <unistd.h>     /* for pause */
#include <signal.h>     /* for signal */

#define INTERVAL 500        /* number of milliseconds to go off */

/* function prototype */
void DoStuff(void);

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

  struct itimerval it_val;  /* for setting itimer */

  /* Upon SIGALRM, call DoStuff().
   * Set interval timer.  We want frequency in ms, 
   * but the setitimer call needs seconds and useconds. */
  if (signal(SIGALRM, (void (*)(int)) DoStuff) == SIG_ERR) 
    perror("Unable to catch SIGALRM");
    exit(1);
  
  it_val.it_value.tv_sec =     INTERVAL/1000;
  it_val.it_value.tv_usec =    (INTERVAL*1000) % 1000000;   
  it_val.it_interval = it_val.it_value;
  if (setitimer(ITIMER_REAL, &it_val, NULL) == -1) 
    perror("error calling setitimer()");
    exit(1);
  

  while (1) 
    pause();



/*
 * DoStuff
 */
void DoStuff(void) 

  printf("Timer went off.\n");


【讨论】:

谢谢你,如果我想让整个警报作为后台运行,我该如何修改它,同时我可以处理一些数据.. 当警报响起时,我写一些东西到文件..正如我之前所说,这两个即处理和文件写入都是异步的.. 非常感谢,我对这个程序做了一些改动,我几乎得到了我想要的..(我现在要为我目前正在工作的数据包捕获项目尝试它) 在您的代码中,您最终会在 main() 中旋转,因此您可以在那里进行处理,而不是空循环。每当您获得 SIGALRM 时,您的代码将暂停,信号处理程序将获得控制权。信号处理程序完成后,您的代码将再次继续。因此,您可以使用信号处理程序设置一个标志,指示您应该写入文件,然后在处理循环中检查该标志。如果已设置,您将写入文件并将标志重置为 false。但是这个解决方案不是异步的,即警报/信号处理程序只会设置一个标志而不是写入文件。 (我上面的空间用完了)你在写文件的时候要小心,这样你正在写的数据结构处于一致的状态,而不是被主进程修改。这就是设置标志的方法很好的原因。

以上是关于需要说明在 GNU C 中使用 settimer 和 alarm 功能的程序的主要内容,如果未能解决你的问题,请参考以下文章

GNU的编译器

SetTimer如何修改间隔时钟uElapse

SetTimer如何修改间隔时钟uElapse

SetTimer如何修改间隔时钟uElapse

SetTimer如何修改间隔时钟uElapse

SetTimer如何修改间隔时钟uElapse