我使用difftime的c函数有时会返回65535

时间:2014-04-24 19:47:48

标签: c

我有一个函数,它使用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(&current_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);
}

2 个答案:

答案 0 :(得分:3)

在查询时间之前,请阅读time(7)手册页(并再次阅读)。

我建议使用clock_gettime(2)例如CLOCK_MONOTONICCLOCK_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来做这件事;除非与某些特定协议或文件格式兼容,否则几乎没有优势。