我想在我的代码中用nanosleep代替过时的ussleep函数:
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 );
问题:这个替换是否得到与ussleep相同的精确定时(它是一个正确的替换)?
struct timespec delay = {0, ( fieldtime - timeleft )}; nanosleep(&delay, NULL);
usleep
过时的原因之一是,当它被信号中断时,其行为在历史系统中是不一致的。根据您的需要,这可能意味着您用nanosleep
进行的简单替换并不完全是您想要的。特别是,当任何信号处理程序被执行时,nanosleep
立即返回,即使信号处理程序安装了SA_RESTART
。所以你可能想这样做:
while (nanosleep(&delay, &delay));
保存被中断时的剩余时间,并在剩余时间内重新启动休眠。
还要注意nanosleep
使用timespec
,其单位为纳秒,而不是微秒。因此,如果您的间隔值以微秒为单位,则必须将其缩放1000以达到纳秒。
另外,要注意传递的纳秒值小于0或大于1000000000(1秒)是错误的(由EINVAL
报告)。timespec
值必须"规范化",即纳秒必须在0到999999999(包括)之间,更大的值转换为使用结构的秒(tv_sec
)字段。
您的潜在目标是在获得前一帧后的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
更改为clock_gettime(CLOCK_MONOTONIC, &performance->input)
设置的struct timespec
而不是gettimeofday()
。CLOCK_MONOTONIC
时钟更适合这种情况,因为它不受系统时间更改的影响。