信号问题,定时器(SIGEV_SIGNAL)

时间:2011-04-27 06:37:06

标签: c linux timer signals

我有一小段代码,我使用了POSIX计时器:timer_create()。使用信号方法(SIGEV_SIGNAL)创建计时器 - 我们的平台不支持SIGEV_THREAD。当计时器到期时,它会生成一个信号SIGUSR1,以通知它的到期,并且有一个相应的处理程序,以捕获此信号,在此处理程序内(在实际程序中,未在代码上显示)我有一个设置的标志,一旦计时器给出的信号被捕获。

提升它,一切都很好:问题是,假设测试程序也生成与定时器相同的信号(在这种情况下为SIGUSR1),则设置相同的标志,而不是定时器。所以没有办法区分,信号处理程序收到的信号是计时器或任何其他测试程序。

你能帮助我解决这个问题吗?

提前致谢。

enter code here
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <string.h>


void sig_handlerTimer1(int);

time_t timerid;
int main()
{
     int i;
     static struct sigaction sa;


     static struct sigevent sevp;  // argument to timer_create
     static struct itimerspec its; // argument to timer_gettime

     memset (&sevp, 0, sizeof (struct sigevent));
     sevp.sigev_value.sival_ptr = &timerid;
     sevp.sigev_notify = SIGEV_SIGNAL;
     sevp.sigev_notify_attributes = NULL;
     sevp.sigev_signo = SIGUSR1;
     sevp.sigev_notify_function=sig_handlerTimer1;

     /* Setting timer interval */
     its.it_interval.tv_sec = 0;
     its.it_interval.tv_nsec = 0;

     /* Setting timer expiration */
     its.it_value.tv_sec = 2;  // First expiry after 1 sec
     its.it_value.tv_nsec = 0;

     /* Setting the signal handlers before invoking timer*/
     sa.sa_handler = sig_handlerTimer1;
     sa.sa_flags = 0;
     sigaction(SIGUSR1, &sa, NULL);

     if (timer_create(CLOCK_REALTIME, &sevp, &timerid) == -1)
     {
             fprintf(stderr, "LeakTracer (timer_trackStartTime): timer_create failed   to create timer. " \
                    "Leak measurement will be for entire duration of the execution   period:%s \n", strerror(errno));
            return;

      }

     if (timer_settime(timerid, 0, &its, NULL) == -1)
     {
             fprintf(stderr, "LeakTracer (timer_trackStartTime): timer_settime failed  to set the timer. " \
                    "Leak measurement will be for entire duration of execution period:%s \n", strerror(errno));
             return;

      }

      for(i=0; i<10; i++)
      {
             printf("%d\n",i);
             if(i==3) {
                 kill(getpid(), SIGUSR1); // SIGUSR1 also generated by test program  which reaches same handler and sets flag (THIS IS UN-DESIRABLE)
              }
             sleep(1);
       }

  }

  void sig_handlerTimer1(int signum)
  {

     int flag = 1;
     printf("Caught signal: %d\n",signum); // How to understand this signal caught, is that of test program of timer expiry?
     if (timer_delete(timerid) < 0)
     {
             fprintf(stderr, "timer deletion failed. " \
                     "This may result in some memory leaks (sig_handlerTimer1):%s \n", strerror(errno));
      }
   }

已添加:是否有任何方法可以知道处理程序内部的计时器是否真的已过期,一旦信号被捕获?

3 个答案:

答案 0 :(得分:4)

您可以通过使用SA_SIGINFO标记和sa_sigaction struct sigaction成员安装信号处理程序来区分信号的原因,然后使用si_code元素siginfo_t *传递给信号处理程序。如果它是SI_TIMER,则信号由定时器到期生成。

答案 1 :(得分:0)

你可能会好起来,因为获得SIGUSR1的唯一方法就是自己生成它,无论是在进程中,使用kill()系统调用还是由于计时器流逝,或使用kill命令从命令行。

您还可以使用SIGUSR2用于任何其他目的。

答案 2 :(得分:0)

Here问题几乎相同,而且正在回答这个问题。 在该解决方案中,他设置指向sigval union的指针,您还可以设置任何int值。 可以在处理程序中检查该值,如果值与您设置的值相同,那么它就是您的信号。以下是sigval联盟的定义:

union sigval {
    int sival_int;
    void *sival_ptr;
}; 

您可以设置seg.sigev_value.sival_int = yourint并在处理程序中通过比较检查相同的值 这样:

if(si->si_value.sival_int == yourint)
 printf("My event");
else
 printf("It's not");

希望这有帮助。