我编写了一个代码来确保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
通常只是一个unsigned
32 位值,因为它不会离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
的定义方式。
使进位工作的正确方法是重新排序求和,首先执行所有加法,然后再进行减法。 这会在同时处理signed
和unsigned
时强制转换为有符号整数,并防止在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;