我有一个函数,它使用difftime来检测自通信心跳停止以来的秒数。此功能可以每50毫秒运行一次。该函数似乎工作,除了偶尔它返回65535.我可以将执行减少到每秒一次,因为difftime的返回仅在几秒钟内。但我不知道它是否能解决这个问题。这是问题,因为我没有正确地将difftime从double转回到uint16_t?
该程序在ubuntu 64位机器上运行。
请帮忙。谢谢。
uint16_t commlost(uint16_t heartbeat_read_cur)
{
time_t current_time;
static time_t previous_time;
static uint16_t commlost_secs_cur = 0;
static uint16_t commlost_secs_prev = 0;
static uint16_t heartbeat_read_prev = 0;
static bool first_time = TRUE;
if (first_time)
{
previous_time = time(NULL);
first_time = FALSE;
}
time(¤t_time);
commlost_secs_prev = commlost_secs_cur;
if(heartbeat_read_prev == heartbeat_read_cur)
{
commlost_secs_cur += difftime(current_time, previous_time);
}
else
{
heartbeat_read_prev = heartbeat_read_cur;
commlost_secs_cur = 0;
}
previous_time = current_time;
return (commlost_secs_cur);
}
答案 0 :(得分:3)
在查询时间之前,请阅读time(7)手册页(并再次阅读)。
我建议使用clock_gettime(2)例如CLOCK_MONOTONIC
或CLOCK_REALTIME
,最好使用double
进行时间计算(因为struct timespec
通常大于任何整数类型)。
请勿使用uint16_t
进行此类时间计算。
尝试使用
inline double double_gettime (clockid_t cid) {
struct timespec ts = {0,0};
clock_gettime(cid, &ts);
return (double)ts.tv_sec + 1.0e-9*ts.tv_nsec;
}
您可能希望通过测试clock_gettime
是否失败并在失败时给予NAN
来使该功能更加出色!这留给读者练习。对于CLOCK_REALTIME
等,您还可以在进程开始的某个时间和当前时间之间测量差异(即计算差异的struct timespec
并将该差异转换为a double
)功能
然后像
double tstart = double_gettime(CLOCK_REALTIME);
some_long_computation();
double tend = double_gettime(CLOCK_REALTIME);
printf ("needed %f seconds to compute\n", tend-tstart);
另见clock(3)
答案 1 :(得分:1)
difftime()
适用于time_t
支持时间分辨率高于整数秒的系统。虽然允许,但我从来没有遇到过这样的系统 - 我不认为有一个存在。具体来说,在POSIX系统上,time_t
以整数秒来衡量,而difftime()
相当于其参数的算术减法,所以实际上你最好只使用:
commlost_secs_cur += current_time - previous_time ;
那就是说,你的实现有点过于复杂,而不是累积自上一次调用以来的时间,这可能小于时钟分辨率,你可以简单地记录观察到的最后一次心跳并从那时起返回时间:
int commlost(uint16_t heartbeat_read_cur)
{
time_t current_time = time(0) ;
static time_t heartbeat_timestamp = 0 ;
static uint16_t heartbeat_read_prev ;
// If first time, or heartbeat changed...
if( heartbeat_timestamp == 0 || heartbeat_read_prev != heartbeat_read_cur)
{
// ... timestamp heartbeat
heartbeat_timestamp = time(0) ;
// ... keep last heartbeat
heartbeat_read_prev = heartbeat_read_cur ;
}
// Return seconds since last heartbeat timestamp
return current_time - heartbeat_timestamp ;
}
我不确定为什么要使用uint16_t
来做这件事;除非与某些特定协议或文件格式兼容,否则几乎没有优势。