Spróbuj zmienić to w następujący sposób, powinno to być dość kosztowne, że nigdy nie przegapisz przebudzenia, ale bądź ostrożny z nim, ponieważ uruchomienie priorytetu w czasie rzeczywistym może zablokować twoją maszynę mocno, jeśli nie zasypia, również być może trzeba wszystko skonfigurować tak, że użytkownik ma możliwość uruchamiania rzeczy z priorytetem czasu rzeczywistego (patrz /etc/security/limits.conf
)
#include <sys/timerfd.h>
#include <time.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <sched.h>
int main(int argc, char *argv[])
{
int timerfd = timerfd_create(CLOCK_MONOTONIC,0);
int milliseconds = atoi(argv[1]);
struct itimerspec timspec;
struct sched_param schedparm;
memset(&schedparm, 0, sizeof(schedparm));
schedparm.sched_priority = 1; // lowest rt priority
sched_setscheduler(0, SCHED_FIFO, &schedparm);
bzero(&timspec, sizeof(timspec));
timspec.it_interval.tv_sec = 0;
timspec.it_interval.tv_nsec = milliseconds * 1000000;
timspec.it_value.tv_sec = 0;
timspec.it_value.tv_nsec = 1;
int res = timerfd_settime(timerfd, 0, &timspec, 0);
if(res < 0){
perror("timerfd_settime:");
}
uint64_t expirations = 0;
int iterations = 0;
while(res = read(timerfd, &expirations, sizeof(expirations))){
if(res < 0){ perror("read:"); continue; }
if(expirations > 1){
printf("%ld expirations, %d iterations\n", expirations, iterations);
break;
}
iterations++;
}
}
Jeśli używasz wątków należy użyć pthread_setschedparam
zamiast sched_setscheduler
.
W czasie rzeczywistym również nie chodzi o małe opóźnienie, chodzi o gwarancje, RT oznacza, że jeśli chcesz się obudzić dokładnie raz na sekundę, to WILL, normalne planowanie nie daje tego, może zdecydować obudźcie się 100 ms później, ponieważ i tak musieliście wykonać jeszcze jedną pracę w tym czasie. Jeśli chcesz się obudzić co 10 ms i NAPRAWDĘ musisz to zrobić, to powinieneś ustawić się tak, by działał jako zadanie w czasie rzeczywistym, wtedy jądro będzie Cię budzić co 10ms bez przerwy.Chyba że zadanie w czasie rzeczywistym o wyższym priorytecie jest zajęte robieniem rzeczy.
Jeśli musisz zagwarantować, że czas przebudzenia jest dokładnie o pewien czas, nie ma znaczenia, czy jest to 1ms lub 1 sekunda, nie dostaniesz go, chyba że uruchomisz jako zadanie w czasie rzeczywistym. Istnieją dobre powody, dla których jądro zrobi to dla ciebie (oszczędzanie energii jest jednym z nich, większa przepustowość to kolejna, są inne), ale jest to w granicach jego uprawnień, ponieważ nigdy nie powiedziałeś, że potrzebujesz lepszych gwarancji. Większość rzeczy nie musi być tak dokładna, lub nie wolno jej przegapić, więc powinieneś pomyśleć o tym, czy naprawdę tego potrzebujesz.
cytując http://www.ganssle.com/articles/realtime.htm
Niełatwe zadanie czas rzeczywisty lub systemu jest jeden gdzie działalność po prostu musi być zakończone - zawsze - przez określony terminie. Ostatecznym terminem może być określony czas lub przedział czasu, lub może być nadejściem jakiegoś wydarzenia. Trudne zadania w czasie rzeczywistym zawodzą, z definicji, , jeśli przegapią taki termin.
Zauważ, że ta definicja nie zakłada żadnych założeń dotyczących lub okresu zadań. Mikrosekunda lub na tydzień - w przypadku braku terminu powoduje awarię, to zadanie ma trudne wymagania w czasie rzeczywistym.
Miękkie realtime jest prawie taka sama, z tym że brakuje terminu, podczas gdy niepożądane, nie jest koniec świata (na przykład wideo i odtwarzania dźwięku są miękkie zadań w czasie rzeczywistym, nie chcesz przegapić wyświetlania ramka lub zabrakło bufora, ale jeśli to zrobisz, to tylko chwilowa czkawka i po prostu kontynuuj). Jeśli to, co próbujesz zrobić, to "miękki" czas rzeczywisty, nie zawracałbym sobie głowy działaniem w priorytecie czasu rzeczywistego, ponieważ generalnie powinieneś dostać swoje przebudzenia na czas (lub przynajmniej blisko).
EDIT:
Jeśli nie są wyświetlane w czasie rzeczywistym jądro będzie domyślnie dać wszystkie zegary wprowadzić pewne „luzu” tak, że można go połączyć swoją prośbę, aby się obudzić z innych zdarzeń, które dzieją się w czasach bliskich ten, o który prosiłeś (to znaczy, jeśli drugie wydarzenie jest w twoim czasie "luzu", to nie obudzi cię w momencie, o który prosiłeś, ale trochę wcześniej lub później, w tym samym czasie już zamierzał zrobić coś innego, to oszczędza energię).
Za trochę więcej informacji patrz High- (but not too high-) resolution timeouts i Timer slack (należy pamiętać, że nie jestem pewien, czy któraś z tych rzeczy jest dokładnie to, co jest naprawdę w jądrze ponieważ oba te artykuły są o LKML lista dyskusyjna dyskusji, ale coś jak pierwszy naprawdę znajduje się w jądrze:
Moje dane na temat okolicy są dość zardzewiałe. Brzmi, że chcesz coś zrobić w czasie rzeczywistym. Sprawdź systemy Linux w czasie rzeczywistym. W przeciwnym razie program planujący używa większej ziarnistości, aby uniknąć wyższych narzutów. Chciałbyś uruchomić swój proces jako RT (w czasie rzeczywistym) ('man sched_setparam') i prawdopodobnie pod rootem. W przypadku normalnych procesów (np. Gier lub multimediów): (1) czekanie w ciasnej pętli lub (2) na każdym zdarzeniu czasomierza obliczyć błąd (oczekiwany v rzeczywisty czas budzenia) i wziąć go na konto przy przejściu na wewnętrzny czas stan zależny. – Dummy00001
Dzięki za napiwek, ale nie uważam 20 milisekundowych interwałów za część domeny czasu rzeczywistego. Znaczy, standardowy system, który ma czekać na 10 milisekund, nigdy nie powinien czekać 21 milisekund, RT brzmi za dużo. –
możesz spróbować ustawić program tak, by działał z priorytetem czasu rzeczywistego, prawdopodobnie nie będziesz potrzebował jądra RT Linuksa, mainline jest całkiem niezły w czasie rzeczywistym i biorąc pod uwagę to, że nigdy nie przegapił więcej niż jednego wygaśnięcia po prostu działającego z priorytetem RT powinno wystarczyć, abyś nigdy nie przegapił żadnego – Spudd86