我有一個循環運行每個X usecs,其中包括做一些I/O然後睡覺剩餘的X usecs。以(大致)計算出的睡眠時間,所有我做的是一個時間戳之前和之後的I/O和減去X.這裏的區別是我使用時間戳功能:使用gettimeofday()自我糾正定期計時器()
long long getus()
{
struct timeval time;
gettimeofday(&time, NULL);
return (long long) (time.tv_sec + time.tv_usec);
}
正如你可以想象的那樣,這開始漂移很快,I/O突發之間的實際時間通常比X多幾毫秒。爲了讓它更準確一點,我想也許如果我保留一條記錄以前的開始時間戳,每當我開始一個新的週期時,我可以計算上一個週期花費多長時間(從這個開始時間戳到前一個週期之間的時間)。然後,我知道它比X多了多久,並且我可以修改我的睡眠來補償這個週期。
這裏是我正在努力實現它:
long long start, finish, offset, previous, remaining_usecs;
long long delaytime_us = 1000000;
/* Initialise previous timestamp as 1000000us ago*/
previous = getus() - delaytime_us;
while(1)
{
/* starting timestamp */
start = getus();
/* here is where I would do some I/O */
/* calculate how much to compensate */
offset = (start - previous) - delaytime_us;
printf("(%lld - %lld) - %lld = %lld\n",
start, previous, delaytime_us, offset);
previous = start;
finish = getus();
/* calculate to our best ability how long we spent on I/O.
* We'll try and compensate for its inaccuracy next time around!*/
remaining_usecs = (delaytime_us - (finish - start)) - offset;
printf("start=%lld,finish=%lld,offset=%lld,previous=%lld\nsleeping for %lld\n",
start, finish, offset, previous, remaining_usecs);
usleep(remaining_usecs);
}
這似乎在循環的第一次迭代工作,但是之後的事情搞的一團糟。
下面是5次迭代循環的輸出:
(1412452353 - 1411452348) - 1000000 = 5
start=1412452353,finish=1412458706,offset=5,previous=1412452353
sleeping for 993642
(1412454788 - 1412452353) - 1000000 = -997565
start=1412454788,finish=1412460652,offset=-997565,previous=1412454788
sleeping for 1991701
(1412454622 - 1412454788) - 1000000 = -1000166
start=1412454622,finish=1412460562,offset=-1000166,previous=1412454622
sleeping for 1994226
(1412457040 - 1412454622) - 1000000 = -997582
start=1412457040,finish=1412465861,offset=-997582,previous=1412457040
sleeping for 1988761
(1412457623 - 1412457040) - 1000000 = -999417
start=1412457623,finish=1412463533,offset=-999417,previous=1412457623
sleeping for 1993507
輸出的第一行顯示前一個週期的時間是如何計算的。看起來前兩個時間戳基本上是1000000us(1412452353 - 1411452348 = 1000005)。然而在此之後,開始時間戳之間的距離開始看起來不那麼合理,以及偏移量。 有誰知道我在這裏做錯了嗎?
編輯:我也歡迎有更好的方法獲得準確的計時器的建議,並在延遲期間能夠睡覺 !