我想在頻率爲十的頻率下中斷,因此從/ dev/rtc中啓用中斷並不理想。我想在中斷之間睡1毫秒或250微秒。如何在Linux中獲得最準確的實時週期性中斷?
啓用從/ dev/HPET週期性中斷工作得很好,但它似乎並沒有在一些機器上工作。顯然,我不能在沒有HPET的機器上使用它。但是我無法在一些有可用時鐘源的機器上工作。例如,在Core 2 Quad上,設置爲輪詢時,內核文檔中包含的示例程序在HPET_IE_ON上失敗。
這將是更好的使用被Linux提供的,而不是直接與硬件設備驅動程序接口的itimer接口。在一些系統中,itimer提供了隨時間推移更穩定的週期性中斷。也就是說,由於hpet不能以我想要的頻率中斷,所以中斷開始偏離牆壁時間。但是我看到有些系統的睡眠方式比使用itimer更長(10+毫秒)。
這是一個使用itimer進行中斷的測試程序。在某些系統上,它只會打印出一個警告,它會在目標時間內睡眠大約100微秒左右。在其他情況下,它會打印出批量的警告,說它在目標時間內睡了10+毫秒。與-lrt編譯和使用sudo CHRT -f 50運行[名]
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <error.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/time.h>
#include <time.h>
#include <signal.h>
#include <fcntl.h>
#define NS_PER_SECOND 1000000000LL
#define TIMESPEC_TO_NS(aTime) ((NS_PER_SECOND * ((long long int) aTime.tv_sec)) \
+ aTime.tv_nsec)
int main()
{
// Block alarm signal, will be waited on explicitly
sigset_t lAlarm;
sigemptyset(&lAlarm);
sigaddset(&lAlarm, SIGALRM );
sigprocmask(SIG_BLOCK, &lAlarm, NULL);
// Set up periodic interrupt timer
struct itimerval lTimer;
int lReceivedSignal = 0;
lTimer.it_value.tv_sec = 0;
lTimer.it_value.tv_usec = 250;
lTimer.it_interval = lTimer.it_value;
// Start timer
if (setitimer(ITIMER_REAL, &lTimer, NULL) != 0)
{
error(EXIT_FAILURE, errno, "Could not start interval timer");
}
struct timespec lLastTime;
struct timespec lCurrentTime;
clock_gettime(CLOCK_REALTIME, &lLastTime);
while (1)
{
//Periodic wait
if (sigwait(&lAlarm, &lReceivedSignal) != 0)
{
error(EXIT_FAILURE, errno, "Failed to wait for next clock tick");
}
clock_gettime(CLOCK_REALTIME, &lCurrentTime);
long long int lDifference =
(TIMESPEC_TO_NS(lCurrentTime) - TIMESPEC_TO_NS(lLastTime));
if (lDifference > 300000)
{
fprintf(stderr, "Waited too long: %lld\n", lDifference );
}
lLastTime = lCurrentTime;
}
return 0;
}
這可能是一個內核錯誤。我的itimer示例似乎在所有使用2.6.32的機器上都能正常工作,但在2.6.35或2.6.38上沒有問題。 – Matt 2011-04-29 15:44:39