Systemy Operacyjne – semestr drugi
Wyk ad dziewi ty
ł
ą
Pomiar czasu i synchronizacja wzgl dem czasu w Linuksie
ę
1.
Generowanie taktów i pomiar up ywu czasu
ł
Wywo ania wielu funkcji j dra s uzale nione nie wyst pieniem okre lonych zdarze lecz up ywem czasu, dlatego j dro systemu musi mie mechanizm pozwalaj cy na
ł
ą
ą
ż
ą
ś
ń
ł
ą
ć
ą
pomiar up ywu czasu. Ten pomiar jest równie potrzebny aplikacjom przestrzeni u ytkownika. Te ostatnie mog wymaga informacji na temat bie
cej daty i czasu, jak
ł
ż
ż
ą
ć
żą
równie mog dokonywa pomiaru czasu wykonania pewnych czynno ci.
ż
ą
ć
ś
G ównym mechanizmem wyznaczaj cym dla j dra up yw kolejnych chwil jest
ł
ą
ą
ł
zegar systemowy. Mechanizm ten generuje w okre lonych odst pach czasu przerwanie
ś
ę
zwane przerwaniem zegarowym, które jest obs ugiwane za pomoc specjalnej procedury obs ugi przerwania. Zegar systemowy pracuje na podstawie impulsów
ł
ą
ł
zegarowych generowanych przez generator impulsów taktuj cych procesor lub przez inne urz dzenia tego typu. Cz stotliwo
generowania kolejnych przerwa przez
ą
ą
ę
ść
ń
zegar systemowy jest okre lona sta
HZ. Znaj c cz stotliwo
mo na wyznaczy d ugo
okresu z jakim dzia a zegar systemowy. W wi kszo ci wspó czesnych
ś
łą
ą
ę
ść
ż
ć
ł
ść
ł
ę
ś
ł
architektur sta a HZ jest równa 100. Wyj tek stanowi mi dzy innymi architektura i368, dla której ta warto wynosi 1000. Zosta a ona zwi kszona 10 krotnie podczas
ł
ą
ę
ść
ł
ę
implementacji j dra w wersji 2.4. Sta a ta ma oczywi cie wp yw na szybko dzia ania systemu. Zwi kszenie jej ma wiele zalet, ale równie mo e powodowa problemy.
ą
ł
ś
ł
ść
ł
ę
ż
ż
ć
Do zalet nale y zaliczy zwi kszenie rozdzielczo ci przerwania zegarowego i zwi kszenie dok adno ci sterowania czasem, co poci ga za sob lepsz obs ug wszystkich
ż
ć
ę
ś
ę
ł
ś
ą
ą
ą
ł
ę
zdarze zale nych od czasu. Niestety nie mo na tej sta ej w dowolny sposób modyfikowa . Nale y równie uwzgl dni fakt, e zwi kszenie tej sta ej poci ga za sob
ń
ż
ż
ł
ć
ż
ż
ę
ć
ż
ę
ł
ą
ą
zwi kszenie cz stotliwo ci wyst powania przerwania zegarowego i cz stszego wywo ywania jego procedury obs ugi. Liczb taktów zegara od momentu uruchomienia
ę
ę
ś
ę
ę
ł
ł
ę
systemu przechowuje si w zmiennej
ę
jiffies, której warto jest zwi kszana o jeden podczas ka dego taktu zegara. Czas pracy systemu (
ść
ę
ż
ang. uptime) mierzony jest jako
iloraz jiffies/HZ. Zmienna jiffies przechowuje warto ci b d ce 64 – bitowymi liczbami naturalnymi. We wcze niejszych wersjach j dra zmienna ta, w architekturach
ś
ę ą
ś
ą
i386 by a 32 – bitowa. Przy HZ=100 przepe nienie jej nast powa o co 497 dni. Kiedy od j dra 2.4 zacz to stosowa sta HZ=1000, to okres ten skróci si do 49,7 dnia,
ł
ł
ę
ł
ą
ę
ć
łą
ł
ę
dlatego te twórcy j dra zastosowali rozwi zanie polegaj ce na „na o eniu” 32 – bitowej zmiennej jiffies na zmienn jiffies_64, która ma rozmiar 64 – bitów. Odwo anie
ż
ą
ą
ą
ł ż
ą
ł
si wi c do zmiennej jiffies w architekturach 32 – bitowych daje warto
jej m odszego s owa, w architekturach 64 – bitowych jej pe n warto . Dost p do pe nej
ę
ę
ść
ł
ł
ł ą
ść
ę
ł
warto ci tej zmiennej jest mo liwy w obu przypadkach poprzez funkcj
ś
ż
ę get_jiffies_64(). Aby unikn
problemów jakie mo e spowodowa przepe nienie tej zmiennej
ąć
ż
ć
ł
programi ci j dra wprowadzili makrodefinicje, uwzgl dniaj ce to zjawisko przy pomiarze czasu. S to
ś
ą
ę
ą
ą
time_after, time_before, time_after_eq i time_before_eq. Do
wszystkich z nich przekazywane s dwa parametry: warto zmiennej jiffies i warto z któr jest ona porównywana. Pierwsza makrodefinicja zwraca warto ró n od
ą
ść
ść
ą
ść
ż ą
zera, je li pierwszy parametr reprezentuje moment wyst puj cy przed momentem reprezentowanym przez parametr drugi. Druga makrodefinicja dzia a odwrotnie.
ś
ę
ą
ł
Dwie pozosta e dodatkowo uwzgl dniaj przypadek, kiedy oba przekazane makrodefinicjom parametry s równe.
ł
ę
ą
ą
Aby aplikacje u ytkownika, które by y napisane z my l o wcze niejszych ni wersja 2.4 j drach mog y dzia a bez przeszkód na j drach 2.4 i pó niejszych,
ż
ł
ś ą
ś
ż
ą
ł
ł ć
ą
ź
wprowadzono sta USER_HZ, która pe ni rol sta ej HZ dla przestrzeni u ytkownika. Ma ona zastosowanie g ównie podczas skalowania warto ci
łą
ł
ę
ł
ż
ł
ś
jiffies dla przestrzeni
u ytkownika. Tej konwersji dokonuje makrodefinicja
ż
jiffies_to_clock(). J dro obs uguje równie mechanizm
ą
ł
ż
zegara czasu rzeczywistego (RTC) z którego pracy korzystają
g ównie aplikacje u ytkowników. Zegar ten przechowuje i aktualizuje informacje o bie
cej dacie i godzinie. Jego zawarto jest odczytywana i umieszczana w zmiennej
ł
ż
żą
ść
xtime podczas rozruchu systemu. J dro nie odczytuje ju wi cej zawarto ci zegara czasu rzeczywistego, ale samo aktualizuje zawarto tej zmiennej i ewentualnie mo e
ą
ż
ę
ś
ść
ż
aktualizowa zawarto samego RTC.
ć
ść
Procedura obs ugi przerwania zegarowego podzielona jest na cz
, która zale na jest od architektury sprz towej i cz
, która jest niezale na. W pierwszej realizowane
ł
ęść
ż
ę
ęść
ż
s cztery czynno ci:
ą
ś
za o enie blokady
ł ż
xtime_lock celem zabezpieczenia dost pu do zmiennej
ę
jiffies_64 i zmiennej xtime,
potwierdzenie obs ugi przerwania b d wyzerowanie licznika dekrementacyjnego,
ł
ą ź
okresowy zapis bie
cej warto ci zmiennej
żą
ś
xtime do RTC,
wywo anie funkcji
ł
do_timer()
Funkcja do_timer() realizuje nast puj ce operacje:
ę
ą
zwi ksza o jeden warto zmiennej jiffies_64,
ę
ść
aktualizuje statystyki wykorzystania zasobów procesu u ytkownika (g ownie czas sp dzony w przestrzeni u ytkownika i przestrzeni systemu), dokonuje
ż
ł
ę
ż
tego za po rednictwem funkcji
ś
update_process_times()
1
,
uruchamia procedury obs ugi liczników dynamicznych, które zako czy y odliczanie,
ł
ń
ł
wywo uje funkcje
ł
scheduler_tick(),
aktualizuje czas w zmiennej xtime,
oblicza obci
enie systemu.
ąż
Bie
cy czas systemowy przechowywany jest w zmiennej
żą
xtime, której typ jest struktur posiadaj c dwa pola. Pierwsze z nich przechowuje liczb sekund, które
ą
ą ą
ę
up yn y od 1 stycznia 1970 roku
ł
ęł
2
, a drugie liczb nanosekund, które up yn y od pocz tku bie
cej sekundy. Zapis i odczyt tej zmiennej wymagaj za o enia blokady
ę
ł
ęł
ą
żą
ą
ł ż
sekwencyjnej xtime_lock. Dla aplikacji u ytkownika ta zmienna jest dost pna poprzez wywo anie
ż
ę
ł
gettimeofday().
2.
Liczniki
Liczniki, zwane licznikami dynamicznymi lub licznikami j dra pozwalaj opó ni wykonanie okre lonych czynno ci o ustalon ilo czasu pocz wszy od chwili bie
cej.
ą
ą
ź ć
ś
ś
ą
ść
ą
żą
Nie jest to mechanizm precyzyjny i mog zdarza si niedok adno ci rz du rozmiaru okresu, wi c nie powinny one by stosowane do zada czasu rzeczywistego,
ą
ć
ę
ł
ś
ę
ę
ć
ń
niemniej wi kszo ci przypadków nadaj si one do zastosowania. Nale y równie pami ta , e liczniki te nie s cykliczne, tzn. po up ywie okre lonego czasu s
ę
ś
ą
ę
ż
ż
ę ć ż
ą
ł
ś
ą
zwalniane i nie jest wznawiana ich praca. Liczniki dynamiczne s reprezentowane struktur
ą
ą timer_list. Aby skorzysta z licznika nale y zadeklarowa zmienn tego
ć
ż
ć
ą
typu, zainicjalizowa j przy pomocy
ć
ą
init_timer(), wype ni bezpo rednio pola
ł ć
ś
expires, data i function, oraz uaktywni przy pomocy
ć
add_timer(). Pierwsze
1
To uaktualnienie nie jest dok adne, ale nie ma potrzeby zmienia je na dok adniejsze.
ł
ć
ł
2
T dat przyjmuje si za pocz tek „epoki Uniksa”.
ę
ę
ę
ą
1
Systemy Operacyjne – semestr drugi
z wymienionych pól okre la czas po którym ma zosta wywo ana zwi zana z licznikiem funkcja, drugie jest parametrem wywo ania tej funkcji
ś
ć
ł
ą
ł
, a trzecie zawiera jej
adres. Wymieniona wcze niej funkcja musi mie nast puj cy prototyp:
ś
ć
ę
ą
void my_timer_function(unsigned long data);
Poniewa funkcja ta mo e by zwi zana równocze nie z kilkoma licznikami, to warto
parametru
ż
ż
ć
ą
ś
ść
data pozwala jej ustali na rzecz którego zosta a wywo ana. Je li
ć
ł
ł
ś
zaistnieje konieczno
modyfikacji momentu wyzwolenia licznika mo na u y w tym celu funkcji
ść
ż
ż ć
mod_timer(). Funkcja ta mo e zosta u yta zarówno dla aktywnych,
ż
ć
ż
jak i nieaktywnych liczników, przy czym te ostatnie s przez ni aktywowane. Je li chcemy usun
aktywny licznik mo emy to uczyni funkcj
ą
ą
ś
ąć
ż
ć
ą del_timer().
W systemach wieloprocesorowych, celem unikni cia sytuacji hazardowych nale y u y
ę
ż
ż ć del_timer_sync(). We wszystkich systemach nale y unika innej modyfikacji
ż
ć
liczników ni przez funkcj
ż
ę mod_timer(), oraz nale y pami ta , aby zabezpieczy zasoby do których dost p wspó bie ny maj funkcje wywo ywane przez liczniki oraz
ż
ę ć
ć
ę
ł
ż
ą
ł
inne cz
ci kodu. Liczniki s powi zane w list . Funkcje przez nie wywo ywane s uruchamiane w kontek cie dolnej po ówki, z poziomu przerwania programowego
ęś
ą
ą
ę
ł
ą
ś
ł
(czyli w kontek cie przerwania), po zako czeniu obs ugi przerwania zegarowego. Aby unikn
sortowania listy liczników i kosztownego przegl dania jest ona
ś
ń
ł
ąć
ą
podzielona na pi
grup, pod wzgl dem czasu po jakim trzeba b dzie wywo a funkcje zgromadzonych na niej liczników.
ęć
ę
ę
ł ć
3.
Opó nianie wykonania
ź
Najprostszym sposobem opó nienia wykonania kodu jest umieszczenie w nim p tli aktywnego oczekiwania. W Linuksie do okre lenia warunku zako czenia takiej p tli
ź
ę
ś
ń
ę
mo na skorzysta z makrodefinicji
ż
ć
time_before(). Wymaga to oczywi cie odczytu zmiennej
ś
jiffies, co mo e rodzi obawy, czy podczas kompilacji nie zostanie ta operacja
ż
ć
zoptymalizowana w niepo
dany sposób. Aby zapobiec takim sytuacjom programi ci j dra zadeklarowali j jako
żą
ś
ą
ą
volatile, co skutecznie powstrzymuje kompilator od
optymalizowania operacji na tej zmiennej. Zalecanym jest, aby w takiej p tli wywo a
ę
ł ć cond_reached(), która powoduje przeszeregowanie zada je li zachodzi taka
ń
ś
potrzeba. Je li czas opó nienia ma by krótki, mo emy pos u y si funkcjami
ś
ź
ć
ż
ł ż ć
ę
udelay() i mdelay(). Pierwsza opó nia wykonanie na jedn mikrosekund wykonuj c
ź
ą
ę
ą
okre lon liczb razy p tl z o on z odpowiednich instrukcji. Liczba iteracji tej p tli jest okre lona zmienn BogoMIPS inicjalizowan przy uruchamianiu j dra.
ś
ą
ę
ę ę ł ż
ą
ę
ś
ą
ą
ą
Funkcja mdelay() korzysta do odliczania czasu z ... funkcji udelay(). Poniewa aktywne oczekiwanie jest nieefektywne i niewskazane wykonanie procesów (w tków
ż
ą
wykonania) mo na opó nia u ywaj c do tego funkcji
ż
ź
ć ż
ą
schedule_timeout() i ustawiaj c stan procesu na TASK_INTERRUPTIBLE
ą
lub TASK_UNINTERRUPTIBLE.
2