定时器和信号中的问题

时间:2011-04-21 07:31:59

标签: c linux timer signals

我已经使用timer_create()API实现了一个POSIX计时器,这将在计时器到期时生成SIGUSR1,我已经为其添加了处理程序代码。现在问题是,如果这个程序收到另一个SIGUSR1,那么将调用并捕获相同的信号处理程序。

有没有办法阻止这种情况,以便处理程序可以捕获仅由计时器生成的信号?

4 个答案:

答案 0 :(得分:13)

这对你有用吗? (修改了timer_create手册页中示例中的代码。)

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>

#define CLOCKID CLOCK_REALTIME
#define SIG SIGUSR1
timer_t timerid;


static void handler(int sig, siginfo_t *si, void *uc)
{
    if(si->si_value.sival_ptr != &timerid){
        printf("Stray signal\n");
    } else {
        printf("Caught signal %d from timer\n", sig);
    }
}

int main(int argc, char *argv[])
{
    struct sigevent sev;
    struct itimerspec its;
    long long freq_nanosecs;
    sigset_t mask;
    struct sigaction sa;

    printf("Establishing handler for signal %d\n", SIG);
    sa.sa_flags = SA_SIGINFO;
    sa.sa_sigaction = handler;
    sigemptyset(&sa.sa_mask);
    sigaction(SIG, &sa, NULL);

    sev.sigev_notify = SIGEV_SIGNAL;
    sev.sigev_signo = SIG;
    sev.sigev_value.sival_ptr = &timerid;
    timer_create(CLOCKID, &sev, &timerid);
    /* Start the timer */

    its.it_value.tv_sec = 10;
    its.it_value.tv_nsec = 0;
    its.it_interval.tv_sec = its.it_value.tv_sec;
    its.it_interval.tv_nsec = its.it_value.tv_nsec;

    timer_settime(timerid, 0, &its, NULL);
    sleep(100);
    exit(EXIT_SUCCESS);
}

当捕获来自计时器的信号时,将显示Caught signal 10 from timer。否则将显示Stray signal

答案 1 :(得分:3)

问题是你是否真的需要使用信号。您可以考虑使用在计时器到期时调用的回调:

void cbf(union sigval);
struct sigevent sev;
timer_t timer;

sev.sigev_notify = SIGEV_THREAD;
sev.sigev_notify_function = cbf; //this function will be called when timer expires
sev.sigev_value.sival_ptr = (void*) arg;//this argument will be passed to cbf
timer_create(CLOCK_MONOTONIC, &sev, &timer);

将在新线程中调用回调函数。

答案 2 :(得分:1)

不,没有简单的方法。如果您还有其他东西与计时器一起生成SIGUSR1,为什么不使用SIGUSR2代替您的计时器。如果这还不够,请为您的应用程序使用其中一个实时信号。

如果它必须能够处理来自定时器和其他来源的相同信号,那么根据速度,数量,系统等等,您可以尝试在定时器注册定时器之前设置时间戳。大约退出,然后在信号处理程序中尝试推断它是否在时间范围内。我强烈建议不要使用这种方法,而是重新设计你正在做的事情。

答案 3 :(得分:1)

使用其他RT信号。查看Is there any way to create a user defined signal in Linux?

上的答案