c语言 - 当我在无限循环中使用 gettimeofday() 时程序意外停止



我编写了一个代码来确保while(1)循环的每个循环都需要特定的时间(在本例中为10000μS,等于0.01秒)。问题是这段代码在开始时运行良好,但不知何故在不到一分钟后停止。这就像访问 Linux 时间是有限制的。现在,我正在初始化一个布尔变量,以使这个时间计算运行一次而不是无限。由于性能随时间而变化,因此最好计算每个循环的计算时间。还有其他方法可以做到这一点吗?

void some_function(){
struct timeval tstart,tend;
while (1){
gettimeofday (&tstart, NULL);
...
Some computation
...
gettimeofday (&tend, NULL);
diff = (tend.tv_sec - tstart.tv_sec)*1000000L+(tend.tv_usec - tstart.tv_usec);
usleep(10000-diff);
}
}

来自 usleep 的手册页

#include <unistd.h>
int usleep(useconds_t usec);

USEC 是无符号的 int,现在猜猜当 diff 在下面行中> 10000 时会发生什么

usleep(10000-diff);

好吧,你为得到差异而进行的计算是错误的:

diff = (tend.tv_sec - tstart.tv_sec)*1000000L+(tend.tv_usec - tstart.tv_usec);

您正在混合不同的整数类型,缺少tv_usec可以是unsigned的数量,您正在从另一个unsigned中减去并且可能会溢出。之后,您将获得整整一秒加上大约4.0E09usec的数量。 这大约是4000秒或一个多小时。近似地。 最好检查是否有一些进位,在这种情况下,递增tv_sec,然后从tv_usec中减去10000000以获得适当的正值。

我不知道您用于struct timeval的实现,但最有可能的是tv_sec是一个time_t(甚至可以是 64 位),而tv_usec通常只是一个unsigned32 位值,因为它不会离1000000更远。

让我说明一下...假设您已经进行了 100 毫秒的计算......而这恰好发生在一秒钟中间......你有

tstart.tv_sec = 123456789; tstart.tv_usec = 123456;
tend.tv_sec = 123456789; tend.tv_usec = 223456;  

当你减去时,它会导致:

tv_sec = 0; tv_usec = 100000;

但是,假设您已经完成了计算,而第二个更改

tstart.tv_sec = 123456789; tstart.tv_usec = 923456;
tend.tv_sec =  123456790; tend.tv_usec = 23456;

时差再次为 100 毫秒,但现在,当您计算表达式时,您会得到第一部分的 1000000(一整秒),但是,在减去第二部分后,您会得到溢出23456 - 923456 =*=> 4294067296(*)。 所以你可以usleep(4295067296)4295s.1h 11m更多。 我想你没有足够的耐心等待它完成......但这是程序可能会发生的事情,具体取决于struct timeval的定义方式。

使进位工作的正确方法是重新排序求和,首先执行所有加法,然后再进行减法。 这会在同时处理signedunsigned时强制转换为有符号整数,并防止在unsigned秒内出现负溢出。

diff = (tend.tv_sec - tstart.tv_sec) * 1000000 + tstart.tv_usec - tend.tv_usec;

解析为

diff = (((tend.tv_sec - tstart.tv_sec) * 1000000) + tstart.tv_usec) - tend.tv_usec;

相关内容

  • 没有找到相关文章

最新更新