मैं आवृत्तियों पर बाधा डालना चाहता हूं जो दस की शक्तियां हैं, इसलिए/dev/rtc से इंटरप्ट को सक्षम करना आदर्श नहीं है। मैं इंटरप्ट्स के बीच 1 मिलीसेकंड या 250 माइक्रोसॉन्ड सोना चाहता हूं।मैं लिनक्स में सबसे सटीक रीयलटाइम आवधिक इंटरप्ट कैसे प्राप्त करूं?
/dev/hpet से आवधिक इंटरप्ट को सक्षम करना बहुत अच्छी तरह से काम करता है, लेकिन ऐसा लगता है कि यह कुछ मशीनों पर काम नहीं करता है। जाहिर है, मैं उन मशीनों पर इसका उपयोग नहीं कर सकता जिनके पास वास्तव में एचपीईटी नहीं है। लेकिन मैं इसे कुछ मशीनों पर काम नहीं कर सकता हूं जिनके पास क्लॉकसोर्स के रूप में उपलब्ध है। उदाहरण के लिए, कोर 2 क्वाड पर, कर्नेल प्रलेखन में शामिल उदाहरण प्रोग्राम HPET_IE_ON पर मतदान पर सेट होने पर विफल रहता है।
हार्डवेयर डिवाइस ड्राइवर के साथ इंटरफेसिंग करने के बजाय लिनक्स द्वारा प्रदान किए गए itimer इंटरफ़ेस का उपयोग करना अच्छा होगा। और कुछ प्रणालियों पर, itimer आवधिक इंटरप्ट प्रदान करता है जो समय के साथ अधिक स्थिर होते हैं। यही कारण है कि, हॉपेट बिल्कुल वांछित आवृत्ति पर बाधा नहीं डाल सकता है, क्योंकि इंटरप्ट्स दीवार के समय से निकलने लगते हैं। लेकिन मैं कुछ सिस्टमों को नींद के रास्ते (10+ मिलीसेकंड) को देख रहा हूं, उन्हें एक आईटीमर का उपयोग करना चाहिए।
यहां इंटरप्ट के लिए itimer का उपयोग कर एक परीक्षण प्रोग्राम है। कुछ प्रणालियों पर यह केवल एक चेतावनी मुद्रित करेगा कि यह लगभग 100 माइक्रोसॉन्ड या फिर लक्ष्य समय पर सो गया है। दूसरों पर, यह चेतावनी के बैच प्रिंट करेगा कि यह लक्ष्य समय पर 10+ मिलीसेकंड सो गया था। -lrt साथ संकलित और 50 -f sudo chrt के साथ चलाने के [नाम]
#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