Posix Timer会定期跳过一半的时间

时间:2011-09-01 20:40:53

标签: c linux timer posix

我有一个与Posix Timer(timer_create())相关联的任务,每20 ms / 50 Hz执行一次。在大多数情况下工作正常,除了每隔334.5秒(大约),计时器在一个周期的早期执行10毫秒。对于接下来的334.5秒,间隔再次为20毫秒。

我已经包含了配置计时器的相关代码。该应用程序在Gumstix Verdex Pro XL6P上运行,并带有Gumstix的默认Linux版本。我还安排了FIFO调度算法。

我的直觉说这是一个整数溢出问题。也许还有其他东西使用相同的信号?我一直能够在棋盘上执行跳过,重复执行和会话。

这个问题并不是一个表演者,但我真的很想知道为什么会这样。

以下是配置计时器的代码:

//------------------------------------------------------------------------------
// Create a timer which fires at the specified time and calls a timer event
// handler.
//
// handler : function to be called when the timer expires
// us      : number of microseconds to add to timer
// ms      : number of milliseconds to add to timer
// sec     : number of seconds to add to timer
//------------------------------------------------------------------------------
void createTimer(void (*handler)(void), uint32 us, uint32 ms, uint32 sec)
{
    struct sigaction sigact;
    struct sigevent sigev;
    timer_t timerid;
    struct itimerspec itval;
    struct itimerspec oitval;
    timer_info_t* newTimer = NULL;

    // Initialize signalNum.
    if (timers == NULL)
        signalNum = SIGRTMAX;

    if (signalNum < SIGRTMIN)
        exitWithError("no avaiable signals, unable to create timers");

    sigemptyset(&sigact.sa_mask);
    sigact.sa_flags = SA_SIGINFO;
    sigact.sa_sigaction = signalHandler;

    // Set up sigaction to catch signal
    if (sigaction(signalNum, &sigact, NULL) == -1)
        exitWithError("sigaction() failed, unabled to creat timers");

    // Create the POSIX timer to generate signo
    sigev.sigev_notify = SIGEV_SIGNAL;
    sigev.sigev_signo = signalNum;
    sigev.sigev_value.sival_ptr = &timerid;        

    long ret = timer_create(CLOCK_REALTIME, &sigev, &timerid);

    if (ret == 0) 
    {
        // Prevent overflow in calculation of nsec below.
        if (ms >= 1000)
        {
            sec += (ms / 1000);
            ms = ms % 1000;
        }

        itval.it_value.tv_sec = sec;
        itval.it_value.tv_nsec = (long)(us * 1000L) + (long)(ms * 1000L * 1000L);

        // Configure it as a repeat timer.
        itval.it_interval.tv_sec = itval.it_value.tv_sec;
        itval.it_interval.tv_nsec = itval.it_value.tv_nsec;

        if (timer_settime(timerid, 0, &itval, &oitval) != 0)
            exitWithError("time_settime() error!");
    }
    else
        exitWithError("timer_create() error!");

    newTimer = (timer_info_t*)malloc(sizeof(timer_info_t));
    newTimer->timer = timerid;
    newTimer->handler = handler;
    newTimer->sigNum = signalNum;
    newTimer->next = NULL;

    // Check to see if this is the first time through.
    if (timers == NULL)
    {
        timers = newTimer;
        atexit(deleteTimers);
    }
    else
        lastTimer->next = newTimer;

    lastTimer = newTimer;

    signalNum--;
}

提前致谢。

1 个答案:

答案 0 :(得分:1)

我的猜测是你正在使用ntp,它正在以这些间隔回转时间。您可以尝试使用CLOCK_MONOTONIC,但根据http://juliusdavies.ca/posix_clocks/clock_realtime_linux_faq.html,它可能也会受到影响。