1

我正在尝试使用 sem_timedwait() 重复锁定和解锁信号量。根据此处的示例,我以以下方式将我的 struct timespec 设置为 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 值?

4

2 回答 2

9

据我所知timespectv_nsec.

您可以做的一件事是:

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

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

于 2014-08-12T01:37:10.103 回答
1

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

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

ts.tv_nsec+=20000000;
if (ts.tv_nsec>=1000000000) {
    ts.tv_sec+=1;
    ts.tv_nsec-=1000000000;
}
于 2014-08-12T00:55:11.830 回答