sha*_*ols 1 c semaphore time.h
我正在尝试使用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;
}
Run Code Online (Sandbox Code Playgroud)
使用上面的代码,我的程序在使用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;
}
Run Code Online (Sandbox Code Playgroud)
我想知道 - 有没有更好的方法来做到这一点,而无需自己直接调整timespec值?
据我所知,你需要正常化一个timespec结构添加的间隔后正常tv_nsec.
你能做的一件事是:
ts.tv_nsec += 20000000;
ts.tv_sec += ts.tv_nsec / 1000000000;
ts.tv_nsec %= 1000000000;
Run Code Online (Sandbox Code Playgroud)
在Linux内核中,您可以使用set_normalized_timespec()为您执行规范化.请参阅此处.