我想在我的代码中用nanosleep替换过时的usleep函数:
static int timediff( struct timeval *large, struct timeval *small )
{
return ( ( ( large->tv_sec * 1000 * 1000 ) + large->tv_usec )
- ( ( small->tv_sec * 1000 * 1000 ) + small->tv_usec ) );
}
struct performance_s
{
struct timeval acquired_input;
};
performance_t *performance_new( int fieldtimeus )
{
performance_t *perf = malloc( sizeof( performance_t ) );
if( !perf ) return 0;
gettimeofday( &perf->acquired_input, 0 );
return perf;
}
performance_t *perf = 0;
int performance_get_usecs_since_frame_acquired( performance_t *perf )
{
struct timeval now;
gettimeofday( &now, 0 );
return timediff( &now, &perf->acquired_input );
}
int fieldtime = videoinput_get_time_per_field( norm );
if( rtctimer ) {
while( performance_get_usecs_since_frame_acquired( perf )
< ( (fieldtime*2) - (rtctimer_get_usecs( rtctimer ) / 2) ) ) {
rtctimer_next_tick( rtctimer );
}
} else {
int timeleft = performance_get_usecs_since_frame_acquired( perf );
if( timeleft < fieldtime )
usleep( fieldtime - timeleft );
问题:这次更换的精确时间是否与usleep相同(并且是正确的替代品)吗?
struct timespec delay = {0, ( fieldtime - timeleft )}; nanosleep(&delay, NULL);
答案 0 :(得分:8)
usleep
过时的原因之一是它被信号中断时的行为在历史系统之间是不一致的。根据您的需要,这可能意味着您对nanosleep
的天真替换并不是您想要的。特别是,nanosleep
在执行任何信号处理程序时立即返回,即使信号处理程序与SA_RESTART
一起安装。所以你可能想做类似的事情:
while (nanosleep(&delay, &delay));
如果中断则保存剩余时间并在剩余时间内重新开始休眠。
另请注意nanosleep
使用timespec
,其中纳秒,而不是微秒。因此,如果您的间隔值以微秒为单位,则必须将它们缩放1000以达到纳秒。
另外,请注意,传递小于0或大于1000000000(1秒)的纳秒值是一个错误(由EINVAL
报告)。 timespec
值必须“标准化”,即纳秒必须介于0和999999999之间(包括),更大的值转换为使用结构的秒(tv_sec
)字段。
答案 1 :(得分:3)
这里的基本目标是睡眠,直到获得上一帧后fieldtime
微秒。 clock_nanosleep()
功能允许您直接执行此操作 - 睡眠直到达到特定的绝对时间 - 因此它更适合您的要求。使用此功能看起来像:
int fieldtime = videoinput_get_time_per_field( norm );
struct timespec deadline = performance->input;
deadline.tv_nsec += fieldtime * 1000L;
deadline.tv_sec += deadline.tv_nsec / 1000000000;
deadline.tv_nsec %= 1000000000;
while (clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &deadline, NULL) && errno == EINTR)
;
这假设您将performance->input
更改为struct timespec
而不是clock_gettime(CLOCK_MONOTONIC, &performance->input)
而不是gettimeofday()
。 CLOCK_MONOTONIC
时钟更适合这种情况,因为它不受系统时间变化的影响。