【问题标题】:How to properly set timespec for sem_timedwait to protect against EINVAL error如何正确设置 sem_timedwait 的 timespec 以防止 EINVAL 错误
【发布时间】:2014-08-12 00:20:52
【问题描述】:

我正在尝试使用 sem_timedwait() 重复锁定和解锁信号量。基于示例here,我以以下方式将我的结构时间规范设置为 20 毫秒超时:

sem_t semaphore;  //initialized somewhere else

void waitForSomething ()
{
    int ret;
    struct timespec ts;

    if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
    {
        //throw error
    }
    ts.tv_nsec += 20000000; //timeout of 20 msec 

    while ((ret = sem_timedwait(&semaphore, &ts)) == -1 && errno == EINTR)
        continue;

    if (ret == -1 && errno != ETIMEDOUT) {
        //flag error
    } else {
        //do something
    }

    return;
}

使用上面的代码,我的程序在运行一段时间后总是会失败,并出现 EINVAL 错误代码。调试后,我意识到失败是因为 ts.tv_nsec 在一段时间后超过了 1000000000。我目前的解决方法如下:

sem_t semaphore;  //initialized somewhere else

void waitForSomething ()
{
    int ret;
    struct timespec ts;

    if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
    {
        //throw error
    }
    if (ts.tv_nsec > 979999999) {
        ts.tv_sec += 60;
        ts.tv_nsec = (ts.tv_nsec + 20000000) % 1000000000;
    } else {
        ts.tv_nsec += 20000000; 
    }

    while ((ret = sem_timedwait(&semaphore, &ts)) == -1 && errno == EINTR)
        continue;

    if (ret == -1 && errno != ETIMEDOUT) {
        //throw error
    } else {
        // do something
    }
    return;
}

我想知道 - 有没有更好的方法来做到这一点,而不必自己直接调整 timespec 值?

【问题讨论】:

    标签: c semaphore time.h


    【解决方案1】:

    据我所知,在向 tv_nsec 添加间隔后,您需要正确规范化 timespec 结构。

    你可以做的一件事是:

    ts.tv_nsec += 20000000;
    ts.tv_sec += ts.tv_nsec / 1000000000;
    ts.tv_nsec %= 1000000000;
    

    在 Linux 内核中,您可以使用set_normalized_timespec() 为您执行规范化。参考here

    【讨论】:

      【解决方案2】:

      您的解决方法似乎是错误的:您想等待 20 毫秒,但在纳秒计数太大的情况下,您添加 60 秒:ts.tv_sec += 60;

      您的解决方法应该如下所示:

      ts.tv_nsec+=20000000;
      if (ts.tv_nsec>=1000000000) {
          ts.tv_sec+=1;
          ts.tv_nsec-=1000000000;
      }
      

      【讨论】:

        猜你喜欢
        • 2016-08-28
        • 2019-08-25
        • 2013-11-16
        • 2012-08-29
        • 2011-07-12
        • 2018-07-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多