sched(7) Miscellaneous Information Manual sched(7)
NAZWA
sched - przeglad szeregowania zadan
OPIS
Od Linuksa 2.6.23, domyslnym planista jest CFS, ,,Completely Fair
Scheduler" (zupelnie sprawiedliwy dyspozytor). Planista CFS zastapil
wczesniejszego dyspozytora ,,O(1)".
Podsumowanie API
Linux udostepnia ponizsze wywolania systemowe, sluzace do kontrolowania
zachowania planisty procesora, algorytmu oraz priorytetow procesow (lub
precyzyjniej: watkow).
nice(2)
Ustawia nowa wartosc nice watku wywolujacego i zwraca nowa
wartosc nice.
getpriority(2)
Zwraca wartosc nice watku, grupy procesow lub zbioru watkow
podanego uzytkownika.
setpriority(2)
Ustawia wartosc watku, grupy procesow lub zbioru watkow podanego
uzytkownika.
sched_setscheduler(2)
Ustawia algorytm i parametry szeregowania podanego watku.
sched_getscheduler(2)
Zwraca algorytm szeregowania podanego watku.
sched_setparam(2)
Ustawia parametry szeregowania podanego watku.
sched_getparam(2)
Pobiera parametry szeregowania podanego watku.
sched_get_priority_max(2)
Zwraca maksymalny dostepny priorytet w danym algorytmie
szeregowania.
sched_get_priority_min(2)
Zwraca minimalny dostepny priorytet w danym algorytmie
szeregowania.
sched_rr_get_interval(2)
Pobiera kwant uzywany wobec watkow szeregowanych przez algorytm
karuzelowy (,,round-robin").
sched_yield(2)
Powoduje zwolnienie procesora przez wywolujacego, dzieki czemu
moze byc wykonany jakis inny watek.
sched_setaffinity(2)
(typowo linuksowe) Ustawia koligacje procesora podanego watku.
sched_getaffinity(2)
(typowo linuksowe) Pobiera koligacje procesora podanego watku.
sched_setattr(2)
Ustawia algorytm i parametry szeregowania podanego watku. To
(typowo linuksowe) wywolanie systemowe zapewnia nadzbior
funkcjonalnosci sched_setscheduler(2) oraz sched_setparam(2).
sched_getattr(2)
Pobiera algorytm i parametry szeregowania podanego watku. To
(typowo linuksowe) wywolanie systemowe zapewnia nadzbior
funkcjonalnosci sched_getscheduler(2) oraz sched_getparam(2).
Algorytmy szeregowania
Planista (dyspozytor) to czesc jadra decydujaca o tym, ktory gotowy do
dzialania watek zostanie wykonany przez procesor jako nastepny. Kazdy
watek ma przypisany algorytm szeregowania zadan oraz statyczny
priorytet szeregowania, sched_priority. Dyspozytor podejmuje swe
decyzje w oparciu o wiedze o algorytmie szeregowania oraz statycznych
priorytetach wszystkich watkow w systemie.
W przypadku watkow korzystajacych z jednego ze zwyklych algorytmow
szeregowania (SCHED_OTHER, SCHED_IDLE, SCHED_BATCH), sched_priority nie
jest stosowane przy podejmowaniu decyzji o szeregowaniu (musi byc
podane jako 0).
Procesy korzystajace z jednego z algorytmow szeregowania czasu
rzeczywistego (SCHED_FIFO, SCHED_RR) maja wartosc sched_priority z
przedzialu od 1 (niski) do 99 (wysoki). Jak wskazuja wartosci, watki
czasu rzeczywistego maja zawsze wyzszy priorytet od zwyklych watkow.
Prosze zauwazyc, ze POSIX.1 wymaga obslugi przez implementacje co
najmniej 32 oddzielnych poziomow priorytetow w przypadku algorytmow
szeregowania czasu rzeczywistego i niektore systemy obsluguja tylko to
minimum. Przenosne programy powinny stosowac sched_get_priority_min(2)
i sched_get_priority_max(2), aby poznac przedzial priorytetow
obslugiwanych dla danego algorytmu.
Idea jest taka, ze dyspozytor zarzadza lista dzialajacych watkow dla
kazdej mozliwej wartosci sched_priority. Aby okreslic nastepny
uruchomiony watek, planista szuka niepustej listy o najwyzszym
statycznym priorytecie i wybiera watek na jej poczatku.
Algorytm szeregowania watku okresla miejsce, w ktorym zostanie on
umieszczony na liscie watkow o takim samym statycznym priorytecie oraz
sposob przemieszczenia sie wewnatrz tej listy.
Wszelkie szeregowanie nastepuje z wywlaszczaniem: jesli pojawi sie
watek o wyzszym priorytecie gotowy do uruchomienia, aktualnie
uruchomiony watek zostanie wywlaszczony i powroci na liste oczekujacych
swego statycznego poziomu priorytetu. Algorytm szeregowania okresla
kolejnosc jedynie na liscie dzialajacych watkow o takim samym
statycznym priorytecie.
SCHED_FIFO: Szeregowanie typu pierwszy na wejsciu, pierwszy na wyjsciu
Algorytm SCHED_FIFO (z ang. first in-first out) mozna stosowac tylko ze
statycznymi priorytetami wyzszymi niz 0, co oznacza, ze gdy watek
SCHED_FIFO stanie sie gotowy do uruchomienia, zawsze natychmiast
wywlaszczy kazdy dzialajacy watek SCHED_OTHER, SCHED_BATCH lub
SCHED_IDLE. SCHED_FIFO jest algorytmem prostego planowania bez podzialu
na wycinki czasowe. Do watkow szeregowanych wedlug algorytmu SCHED_FIFO
stosuja sie nastepujace reguly:
o Dzialajacy watek SCHED_FIFO wywlaszczony przez inny watek o wyzszym
priorytecie pozostanie na czele listy swojego priorytetu i wznowi
wykonanie, gdy tylko wszystkie watki o wyzszym priorytecie zostana
ponownie zablokowane.
o Gdy zablokowany watek SCHED_FIFO stanie sie gotowy do uruchomienia,
zostanie umieszczony na koncu listy swojego priorytetu.
o Gdy wywolanie do sched_setscheduler(2), sched_setparam(2),
sched_setattr(2), pthread_setschedparam(3) lub
pthread_setschedprio(3) zmieni priorytet dzialajacego lub gotowego
do dzialania watku SCHED_FIFO, identyfikowanego przez pid, efekt
pozycji watku na liscie zalezy od kierunku zmiany priorytetu watku:
(a) Jesli podnosi sie priorytet watku, jest on umieszczany na koncu
listy jego nowego priorytetu. Moze zatem wywlaszczyc aktualnie
dzialajacy watek o tym samym priorytecie.
(b) Jesli priorytet watku nie ulega zmianie, jego pozycja na liscie
nie ulega zmianie.
(c) Jesli obniza sie priorytet watku, jest on umieszczany na czele
listy jego nowego priorytetu.
Zgodnie z POSIX.1-2008, zmiany priorytetu (lub algorytmu
szeregowania) watku, dokonane mechanizmem innym niz
pthread_setschedprio(3), powinny spowodowac umieszczenie watku na
koncu listy jego priorytetu.
o Watek wywolujacy sched_yield(2) zostanie umieszczony na koncu listy.
Nie wystepuja inne zdarzenia mogace przesunac watek szeregowany wedlug
algorytmu SCHED_FIFO na liscie oczekujacych watkow gotowych do
dzialania o tym samym priorytecie statycznym.
Watek SCHED_FIFO dziala do momentu zablokowania przez zadanie
wejscia/wyjscia, wywlaszczenia przez watek o wyzszym priorytecie lub
wywolania przez niego sched_yield(2).
SCHED_RR: Szeregowanie rotacyjne (karuzelowe)
Algorytm SCHED_RR (z ang. round-robin) jest prostym rozszerzeniem
SCHED_FIFO. Wszystko, co opisano powyzej wobec SCHED_FIFO, stosuje sie
rowniez wobec SCHED_RR z tym wyjatkiem, ze kazdy watek moze dzialac
jedynie przez maksymalny kwant czasu. Jesli watek SCHED_RR dzialal
przez czas rowny lub dluzszy kwantowi czasu, zostanie umieszczony na
koncu listy dla jego priorytetu. Watek SCHED_RR wywlaszczony przez
watek o wyzszym priorytecie, ktory nastepnie wznowil dzialanie jako
watek dzialajacy, ukonczy niewygasly fragment swojego kwantu czasu
szeregowania rotacyjnego. Dlugosc kwantu czasu mozna pozyskac za pomoca
sched_rr_get_interval(2).
SCHED_DEADLINE: Szeregowanie sporadyczne z budzetem czasu
Od Linuksa 3.14, Linux udostepnia szeregowanie sporadyczne z budzetem
czasu (SCHED_DEADLINE). Ten algorytm zaimplementowano obecnie za pomoca
GEDF (Global Earliest Deadline First) w polaczeniu z CBS (Constant
Bandwidth Server). Aby ustawic i pobrac ten algorytm wraz z powiazanymi
atrybutami, konieczne jest uzycie typowo linuksowych wywolan
systemowych sched_setattr(2) i sched_getattr(2).
Zadaniem sporadycznym jest takie, ktore ma sekwencje zadan, z ktorych
kazde jest aktywowane co najwyzej raz na okres. Kazde zadanie ma tez
limit wzgledny, przed ktorym powinno ukonczyc wykonanie oraz czas
obliczeniowy, ktory jest czasem procesora potrzebnym na wykonanie
zadania. Moment, w ktorym zadanie wybudza sie, ze wzgledu na nowa prace
do wykonania, nazywa sie momentem nadejscia (rowniez momentem zadania
lub momentem zwolnienia). Moment uruchomienia to czas, w ktorym zadanie
rozpoczyna swe wykonywanie. Limit absolutny powstaje zatem przez
dodanie limitu wzglednego do czasu nadejscia.
Ponizszy diagram ukazuje powyzsze pojecia:
nadejscie/wybudzenie limit absolutny
| moment uruchomienia |
| | |
v v v
-----x--------xooooooooooooooooo--------x--------x---
|<- czas obl. -->|
|<-------- limit wzgledny -------->|
|<-------------- okres -------------------->|
Przy ustawianiu algorytmu SCHED_DEADLINE wobec watku za pomoca
sched_setattr(2), mozna podac trzy parametry: Czas Dzialania (Runtime),
Limit (Deadline) oraz Okres (Period). Parametry te niekoniecznie
odpowiadaja wczesniej wymienionym pojeciom: praktyka jest zwykle
ustawienie Czasu Dzialania na wartosc wieksza niz przecietny czas
obliczeniowy (lub czas wykonania w najgorszym wariancie, w przypadku
trudnych zadan czasu rzeczywistego), Limit na limit wzgledny a Okres na
okres zadania. Zatem w szeregowaniu SCHED_DEADLINE mamy:
nadejscie/wybudzenie limit absolutny
| moment uruchomienia |
| | |
v v v
-----x--------xooooooooooooooooo--------x--------x---
|<- Czas Dzialania ->|
|<------------- Limit ------------>|
|<-------------- Okres -------------------->|
Trzy parametry niniejszego szeregowania odpowiadaja polom
sched_runtime, sched_deadline oraz sched_period struktury sched_attr;
zob. sched_setattr(2). Pola te wyrazaja wartosci w nanosekundach. Jesli
poda sie sched_period jako 0, przyjmowana jest wartosc taka sama jak w
sched_deadline.
Jadro wymaga aby:
sched_runtime <= sched_deadline <= sched_period
Dodatkowo, w biezacej implementacji, wszystkie wartosci parametrow
musza wynosic przynajmniej 1024 (tj. odrobine ponad jedna mikrosekunde,
stanowiaca rozdzielczosc implementacji) i mniej niz 2^63. Jesli ktorys
z tych warunkow nie bedzie spelniony, sched_setattr(2) zawiedzie z
bledem EINVAL.
CBS gwarantuje brak interferencji pomiedzy zadaniami, poprzez dlawienie
watkow probujacych przekroczyc ich okreslony Czas Dzialania.
Aby zagwarantowac szeregowanie z budzetem czasu, jadro musi zapobiegac
sytuacjom, gdy uszeregowanie zbioru watkow SCHED_DEADLINE jest
nierealistyczne w podanych ograniczeniach czasowych. Jadro dokonuje
zatem testu przyjecia przy ustawianiu lub zmienianiu algorytmu i
atrybutow SCHED_DEADLINE. Test przyjecia polega na obliczeniu, czy
zmiana jest realistyczna: jesli nie jest, sched_setattr(2) zawiedzie z
bledem EBUSY.
Na przyklad, jest wymagane (lecz niekoniecznie wystarczajace), aby
calkowite uzycie bylo mniejsze lub rowne calkowitej liczbie dostepnych
procesorow, poniewaz kazdy watek moze dzialac maksymalnie przez Czas
Dzialania na Okres, czyli jego uzycie wynosi Czas Dzialania dzielony
przez jego Okres.
Aby wypelnic gwarancje uczynione przy przyjeciu watku przez algorytm
SCHED_DEADLINE, watki SCHED_DEADLINE sa watkami o najwyzszym
(kontrolowanym przez uzytkownika) priorytecie w systemie; jesli dziala
jakis watek SCHED_DEADLINE, wywlaszczy on wszystkie watki szeregowane
wedlug innych algorytmow.
Wywolanie fork(2) przez watek szeregowany wedlug algorytmu
SCHED_DEADLINE zawiedzie z bledem EAGAIN, chyba ze watek ma ustawiony
swoj znacznik reset-on-fork (zob. nizej).
Watek SCHED_DEADLINE po wywolaniu sched_yield(2) zwolni biezaca prace i
zaczeka na rozpoczecie nowego okresu.
SCHED_OTHER: Domyslny sposob szeregowania zadan w Linuksie
Algorytm SCHED_OTHER mozna stosowac tylko ze statycznym priorytetem 0
(tj. watki szeregowane przez algorytmy czasu rzeczywistego sa zawsze
priorytetowe wobec procesow SCHED_OTHER). SCHED_OTHER jest standardowym
algorytmem szeregowania w Linuksie, przeznaczonym do wszystkich watkow
niewymagajacych specjalnych mechanizmow czasu rzeczywistego.
Watek do uruchomienia jest wybierany z listy o statycznym priorytecie
0, w oparciu o priorytet dynamiczny, okreslany jedynie wewnatrz tej
listy. Priorytet dynamiczny bazuje na wartosci nice (zob. nizej) i jest
zwiekszany przy kazdym kwancie czasu, w ktorym watek jest gotowy do
uruchomienia, ale odmowil mu tego dyspozytor (tzw. postarzanie watku).
W ten sposob uzyskuje sie sprawiedliwy postep dla wszystkich watkow
SCHED_OTHER.
W kodzie zrodlowym jadra Linux, algorytm SCHED_OTHER nazywa sie tak
naprawde SCHED_NORMAL.
Wartosc nice
Wartosc nice jest atrybutem, ktory mozna wplynac na dyspozytora, aby
faworyzowal (lub przeciwnie) proces w decyzjach szeregowania zadan.
Wplywa na szeregowanie procesow SCHED_OTHER i SCHED_BATCH (zob. nizej).
Wartosc nice mozna modyfikowac za pomoca nice(2), setpriority(2) lub
sched_setattr(2).
Zgodnie z POSIX.1, wartosc nice jest atrybutem przynaleznym procesowi;
tj. watki procesu powinny dzielic wartosc nice. Jednak w Linuksie
wartosc nice jest atrybutem przynaleznym watkowi: rozne watki tego
samego procesu moga miec rozne wartosci nice.
Przedzial wartosci nice rozni sie miedzy systemami UNIX. We
wspolczesnym Linuksie przedzial wynosi od -20 (wysoki priorytet) do +19
(niski priorytet). W niektorych innych systemach wynosi on -20..20.
Bardzo wczesne jadra Linux (przed Linuksem 2.0) korzystaly z przedzialu
-nieskonczonosc..15.
Poziom wplywu wartosci nice na relatywne szeregowanie procesow
SCHED_OTHER rowniez rozni sie miedzy systemami UNIX oraz pomiedzy
wersjami jadra Linux.
Wraz z wprowadzeniem dyspozytora CFS w Linuksie 2.6.23, Linux przyjal
algorytm przewidujacy znacznie wiekszy wplyw relatywnych roznic
wartosci nice. W biezacej implementacji, roznica kazdej jednosci w
wartosci nice pomiedzy dwoma procesami stanowi mnoznik 1,25, o jaki
planista faworyzuje proces o wyzszym priorytecie. Powoduje to
zapewnienie rzeczywiscie niewielkiego czasu procesora procesom o bardzo
niskim priorytecie (wartosc nice +19), gdy w systemie wystepuja
istotniejsze zadania oraz udostepnia wiekszosc procesora przy wysokim
priorytecie (wartosc nice -20) aplikacjom, ktore tego wymagaja (np.
niektore programy zwiazane z dzwiekiem).
W Linuksie, za pomoca limitu zasobow RLIMIT_NICE, mozna zdefiniowac
limit wartosc nice, jaki moze uzyskac nieuprzywilejowany proces; wiecej
szczegolow w podreczniku setrlimit(2).
Wiecej szczegolow na temat wartosci nice opisano ponizej, w
podrozdzialach o funkcji autogrupowania i szeregowania grup.
SCHED_BATCH: Szeregowanie procesow wsadowych
(Od Linuksa 2.6.16). Algorytm SCHED_BATCH mozna stosowac wylacznie ze
statycznym priorytetem 0. Algorytm podobny do SCHED_OTHER w tym, ze
szereguje watki zgodnie z ich priorytetem dynamicznym (bazujacym na
wartosci nice). Roznica jest taka, ze tutaj dyspozytor zawsze zaklada,
ze watek jest obciazajacy dla procesora. W konsekwencji, planista
zastosuje niewielka kare przy wybudzeniu, co powoduje umiarkowanie
rzadsze przydzielanie mu zasobow.
Algorytm przydatny w przypadku obciazen nieinteraktywnych, ktore jednak
nie chca zmniejszac swojego priorytetu poprzez wartosc nice oraz w
przypadku obciazen wymagajacych deterministycznego algorytmu
szeregowania, bez dodatkowego wywlaszczania wywolywanego przez
interaktywnosc (pomiedzy ich zadaniami).
SCHED_IDLE: Szeregowanie zadan o bardzo niskim priorytecie
(Od Linuksa 2.6.23). Algorytm SCHED_IDLE mozna stosowac tylko ze
statycznym priorytetem 0; wartosc nice procesu nie ma na niego wplywu.
Przeznaczony do uruchamiania zadan o ekstremalnie niskim priorytecie
(nizszym nawet niz wartosc nice +19 w algorytmach SCHED_OTHER lub
SCHED_BATCH).
Resetowanie algorytmu szeregowania procesow potomnych
Kazdy watek ma znacznik szeregowania reset-on-fork (zresetuj przy
rozwidleniu). Gdy jest ustawiony, potomkowie utworzeni przy fork(2) nie
dziedzicza uprzywilejowanych algorytmow szeregowania. Znacznik
reset-on-fork moze byc ustawiony przez:
o zsumowanie (logiczne OR) znacznika SCHED_RESET_ON_FORK do argumentu
policy przy wywolaniu sched_setscheduler(2) (od Linuksa 2.6.32);
albo
o podanie znacznika SCHED_FLAG_RESET_ON_FORK w attr.sched_flags przy
wywolaniu sched_setattr(2).
Prosze zauwazyc, ze stale uzywane przez oba interfejsy maja rozne
nazwy. Stan znacznika reset-on-fork mozna analogicznie pobrac za pomoca
sched_getscheduler(2) i sched_getattr(2).
Funkcja reset-on-fork jest przeznaczona do aplikacji odtwarzajacych
media i moze posluzyc do unikniecia mozliwosci ominiecia przez
aplikacje limitu zasobu RLIMIT_RTTIME (zob. getrlimit(2)) przez
tworzenie wielu procesow potomnych.
Precyzyjniej: jesli ustawiono znacznik reset-on-fork, do nowo
tworzonych potomkow stosuja sie nastepujace zasady:
o Jesli watek wywolujacy ma ustawiony algorytm szeregowania SCHED_FIFO
lub SCHED_RR, algorytm jest resetowany na SCHED_OTHER w procesach
potomnych.
o Jesli proces wywolujacy ma ujemna wartosc nice, wartosc nice jest
resetowana na zero w procesach potomnych.
Po wlaczeniu znacznika reset-on-fork, mozna go zresetowac tylko, jesli
watek ma przywilej CAP_SYS_NICE. Znacznik jest wylaczony w procesach
potomnych tworzonych przez fork(2).
Przywileje i limity zasobow
Przed Linuksem 2.6.12, tylko watki uprzywilejowane (CAP_SYS_NICE) moga
miec ustawiony niezerowy priorytet statyczny (tj. ustawiony algorytm
szeregowania czasu rzeczywistego). Jedyna zmiane, jaka moze dokonac
nieuprzywilejowany watek, jest ustawienie algorytmu SCHED_OTHER, a to
mozna zrobic tylko, jesli efektywny identyfikator uzytkownika
wywolujacego jest rowny rzeczywistemu lub efektywnemu identyfikatorowi
uzytkownika watku docelowego (tj. watku okreslonemu przez pid), ktorego
algorytm jest zmieniany.
Watek musi byc uprzywilejowany (CAP_SYS_NICE), aby ustawic lub
zmodyfikowac algorytm SCHED_DEADLINE.
Od Linuksa 2.6.12, limit zasobow RLIMIT_RTPRIO definiuje gorny limit
statycznego priorytetu watku nieuprzywilejowanego w algorytmach
SCHED_RR i SCHED_FIFO. Reguly zmiany algorytmow szeregowania i
priorytetow sa nastepujace:
o Jesli nieuprzywilejowany watek ma niezerowy miekki limit
RLIMIT_RTPRIO, to moze zmienic swoj algorytm szeregowania zadan i
priorytet, z takim ograniczeniem, ze priorytet nie moze byc
ustawiony na wyzszy niz maksymalna z wartosci: jego biezacego
priorytetu i jego limitu miekkiego RLIMIT_RTPRIO.
o Jesli miekki limit RLIMIT_RTPRIO wynosi 0, to jedynymi dozwolonymi
zmianami sa: obnizenie priorytetu lub przelaczenie z algorytmu czasu
rzeczywistego na niebedacy takowym.
o Wedle tych samych zasad, inny nieuprzywilejowany watek moze rowniez
dokonac tych zmian, o ile efektywny identyfikator uzytkownika watku
dokonujacego zmiany jest taki sam, jak rzeczywisty lub efektywny
identyfikator uzytkownika watku docelowego.
o Specjalne zasady tycza sie algorytmu SCHED_IDLE. Przed Linuksem
2.6.39, nieuprzywilejowany watek dzialajacy wedlug tego algorytmu
nie mogl go zmienic, niezaleznie od wartosci jego limitu zasobow
RLIMIT_RTPRIO. Od Linuksa 2.6.39, nieuprzywilejowany watek moze
przelaczyc sie na algorytm SCHED_BATCH lub SCHED_OTHER, o ile jego
wartosc nice znajduje sie w przedziale dozwolonym przez jego limit
zasobow RLIMIT_NICE (zob. getrlimit(2)).
Watki uprzywilejowane (CAP_SYS_NICE) ignoruja limit RLIMIT_RTPRIO;
podobnie jak w starszych jadrach, moga dokonywac dowolnych zmian
dotyczacych algorytmu szeregowania zadan i priorytetow. Wiecej
informacji na temat RLIMIT_RTPRIO znajduje sie w podreczniku
getrlimit(2).
Ograniczanie uzycia procesora przez procesy czasu rzeczywistego i z
budzetem czasu
Nieblokujaca, nieskonczona petla w watku zaszeregowanym wedlug
algorytmu SCHED_FIFO, SCHED_RR lub SCHED_DEADLINE potencjalnie moze na
zawsze zablokowac dostep do procesora wszystkim innym watkom. Przed
Linuksem 2.6.25, jedynym sposobem zapobiegniecia zamrozenia systemu
przez zbiegly proces czasu rzeczywistego bylo uruchomienie (na konsoli)
powloki zaszeregowanej z wyzszym priorytetem statycznym niz testowana
aplikacja. Mozna bylo w ten sposob awaryjnie zabic testowana aplikacje
czasu rzeczywistego, ktora nie zablokowala lub nie zakonczyla sie
zgodnie z oczekiwaniami.
Od Linuksa 2.6.25, istnieja inne techniki radzenia sobie ze zbieglymi
procesami czasu rzeczywistego i z budzetem czasu. Jedna z nich jest
uzycie limitu zasobow RLIMIT_RTTIME do nalozenia ograniczenia na czas
procesora, jaki moze skonsumowac proces czasu rzeczywistego. Wiecej
szczegolow w podreczniku getrlimit(2).
Od Linuksa 2.6.25, Linux zapewnia rowniez dwa pliki /proc, ktore moga
posluzyc do zarezerwowania okreslonej ilosci czasu procesora dla
procesow innych niz czasu rzeczywistego. Zarezerwowanie czasu procesora
w ten sposob, pozwala rowniez na przydzielenie pewnej ilosci czasu
procesora dla (przykladowo) powloki roota, z ktorej mozna zabic zbiegly
proces. Oba pliki okreslaja wartosci czasu w mikrosekundach:
/proc/sys/kernel/sched_rt_period_us
Plik okresla ,,okres szeregowania zadan" rownowazny 100%
przepustowosci procesora. Wartosc w pliku moze byc z zakresu od
1 do INT_MAX, czyli od 1 mikrosekundy do okolo 35 minut.
Domyslna wartosc w pliku wynosi 1 000 000 (1 sekunda).
/proc/sys/kernel/sched_rt_runtime_us
Wartosc w tym pliku okresla, jak duzo tego ,,okresu szeregowania
zadan" w systemie moze byc przeznaczone na wszystkie procesy
czasu rzeczywistego oraz procesy szeregowane z budzetem czasu.
Wartosc w pliku moze byc z zakresu od -1 do INT_MAX-1. Podanie
-1 uczyni ten czas takim samym jak ten okres; tj. nie odklada
sie czasu procesora na procesy inne niz czasu rzeczywistego
(takie zachowanie wystepowalo przed Linuksem 2.6.25). Wartosc
domyslna w pliku to 950 000 (0,95 sekundy), co oznacza ze 5%
czasu procesora jest zarezerwowane na procesy szeregowane wedle
algorytmow innych niz czasu rzeczywistego i z budzetem czasu.
Czas odpowiedzi
Zablokowany watek o wysokim priorytecie oczekujacy na wejscie/wyjscie
ma okreslony czas odpowiedzi, zanim zostanie ponownie zaszeregowany.
Sterownik zapisujacy urzadzenia moze znacznie ograniczyc ten czas
odpowiedzi poprzez korzystanie z procedury obslugi przerwan zwanej
,,slow interrupt".
Rozne
Procesy potomne dziedzicza algorytm i parametry szeregowania poprzez
fork(2). Algorytm i parametry szeregowania sa zachowywane poprzez
execve(2).
W przypadku procesow czasu rzeczywistego, aby uniknac opoznien
zwiazanych ze stronicowaniem, potrzebne jest zwykle blokowanie pamieci;
mozna go dokonywac za pomoca mlock(2) lub mlockall(2).
Funkcja autogrupowania
Od Linuksa 2.6.38, jadro zapewnia funkcje zwana autogrupowaniem, ktora
ma na celu poprawienie wydajnosci interaktywnych srodowisk graficznych,
podczas wykonywania wieloprocesowych, mocno obciazajacych procesor
prac, takich jak budowanie jadra Linux z wieloma rownoleglymi procesami
budowania (tj. z opcja -j make(1)).
Funkcja dziala razem z planista CFS i wymaga, aby jadro bylo
skonfigurowane z opcja CONFIG_SCHED_AUTOGROUP. W dzialajacym systemie,
funkcje mozna wlaczyc lub wylaczyc poprzez plik
/proc/sys/kernel/sched_autogroup_enabled; wartosc 0 wylacza te funkcje,
a wartosc 1 ja wlacza. Domyslna wartoscia w pliku jest 1, chyba ze
podczas rozruchu jadra ustawiono parametr noautogroup.
Nowa autogrupa jest tworzona przy tworzeniu nowej sesji za pomoca
setsid(2); dzieje sie tak np. przy uruchamianiu nowego okna terminala.
Nowy proces tworzony przez fork(2) dziedziczy czlonkostwo w autogrupie
swojego rodzica. Wszystkie procesy w sesji sa zatem czlonkami tej samej
autogrupy. Autogrupa jest automatycznie niszczona, gdy zakonczy sie
ostatni proces grupy.
Gdy autogrupowanie jest wlaczone, wszyscy czlonkowie autogrupy sa
umieszczani w tej samej ,,grupie zadan" dyspozytora jadra. Gdy jest
wylaczone, tworzenie grup odbywa sie tak samo, czlonkostwo w autogrupie
jest wciaz widoczne w /proc, lecz autogrupy nie sa uzywane. Planista
CFS uzywa algorytmu wyrownujacego rozlozenie cykli procesora pomiedzy
grupami zadan. Korzysci, jakie z tego wynikaja dla wydajnosci
interaktywnego srodowiska graficznego moze przyblizyc nastepujacy
przyklad.
Zalozmy, ze sa dwie autogrupy rywalizujace o ten sam procesor (tj. moze
byc to system jednoprocesorowy albo wykorzystano taskset(1) do
ograniczenia wszystkich procesow do tego samego procesora w
wieloprocesorowym systemie SMP). Pierwsza grupa zawiera dziesiec
procesow ograniczonych wydajnoscia procesora, pochodzacych od polecenia
budujacego jadro: make -j10. Druga zawiera jeden proces ograniczony
wydajnoscia procesora: odtwarzacz wideo. Efekt autogrupowania jest
taki, ze obie grupy otrzymaja po polowie cykli procesora. Odtwarzacz
wideo otrzyma zatem 50% cykli procesora, zamiast 9%, ktore
najprawdopodobniej odbily by sie negatywnie na ciaglosci odtwarzania
wideo. Sytuacja w wieloprocesorowym systemie SMP jest bardziej zlozona,
ale ogolny efekt jest taki sam: dyspozytor rozklada cykle procesora
pomiedzy poszczegolne grupy zadaniowe w ten sposob, ze autogrupy
zawierajace duza liczbe procesow ograniczonych wydajnoscia procesora
nie zmonopolizuja cykli procesora kosztem innych zadan systemu.
Czlonkostwo procesu w autogrupie (grupie zadan) mozna sprawdzic w pliku
/proc/pid/autogroup:
$ cat /proc/1/autogroup
/autogroup-1 nice 0
Za pomoca tego pliku mozna tez zmodyfikowac przydzial procesora
przypisany autogrupie. Robi sie to zapisujac liczbe z przedzialu
wartosci ,,nice" do pliku, co powoduje przypisanie wartosci nice
autogrupie. Dozwolony zakres to od +19 (niski priorytet) do -20 (wysoki
priorytet). Zapisanie wartosci spoza tego przedzialu spowoduje
zgloszenie przez write(2) bledu EINVAL.
Ustawienie nice autogrupy ma takie samo znaczenie jak wartosc nice
procesu, jednak odnosi sie do rozlozenia cykli procesora do autogrupy
jako calosci, w oparciu o relatywne wartosci nice innych autogrup. W
przypadku procesu wewnatrz autogrupy, cykle procesora jakie on otrzyma
beda skutkiem lacznego oddzialywania wartosci nice autogrupy (w
porownaniu z innymi autogrupami) oraz wartosci nice procesu (w
porownaniu z innymi procesami tej samej autogrupy).
Korzystanie z kontrolera procesora cgroups(7) do umieszczania procesow
w grupach kontrolnych (cgroup) innych niz glowna grupa kontrolna
procesora przeslania efekt dzialania autogrupowania.
Funkcja autogrupowania grupuje jedynie procesy szeregowane wedlug
algorytmow innych niz czasu rzeczywistego (tj. dotyczy algorytmow
SCHED_OTHER, SCHED_BATCH i SCHED_IDLE). Nie grupuje procesow
szeregowanych wedlug algorytmow czasu rzeczywistego oraz z budzetem
czasu. Takie procesy sa szeregowane zgodnie z zasadami opisanymi
wczesniej.
Wartosc nice oraz szeregowanie grup
Przy szeregowaniu procesow innych niz czasu rzeczywistego (tj.
szeregowanych wedlug algorytmow SCHED_OTHER, SCHED_BATCH i SCHED_IDLE),
dyspozytor CFS uzywa techniki znanej jako ,,szeregowanie grup", jesli
tylko jadro skonfigurowano z opcja CONFIG_FAIR_GROUP_SCHED (jest to
opcja typowo wlaczona).
W szeregowaniu grup, watki sa szeregowane w ,,grupach zadan". Grupy
zadan maja relacje hierarchiczna, zakorzeniona w pierwotnej grupie
zadaniowej systemu, zwanej ,,glowna grupa zadan". Grupy zadan sa
tworzone w nastepujacych okolicznosciach:
o Wszystkie watki grupy kontrolnej (cgroup) procesora tworza grupe
zadan. Rodzicem tej grupy zadan jest grupa zadan odpowiadajacej
rodzicielskiej grupy kontrolnej.
o Jesli autogrupowanie jest wlaczone, wszystkie watki, ktore sa (w
sposob dorozumiany) umieszczane w autogrupie (tj. z tej samej sesji,
tworzonej przez setsid(2)) tworza grupe zadan. Kazda nowa autogrupa
jest zatem oddzielna grupa zadan. Glowna grupa zadan jest rodzicem
wszystkich takich autogrup.
o Jesli autogrupowanie jest wlaczone, glowna grupa zadan sklada sie ze
wszystkich procesow w glownej grupie kontrolnej procesora, ktore nie
zostaly w sposob dorozumiany umieszczone w nowej autogrupie.
o Jesli autogrupowanie jest wylaczone, glowna grupa zadan sklada sie
ze wszystkich procesow w glownej grupie kontrolnej procesora.
o Jesli wylaczono szeregowanie grup (tj. jadro skonfigurowano bez
opcji CONFIG_FAIR_GROUP_SCHED), wszystkie procesy w systemie sa jak
gdyby umieszczane w jednej grupie zadan.
Przy korzystaniu z szeregowaniu grup, wartosc nice watku ma znaczenie
przy decyzjach szeregowania tylko wzgledem innych watkow w tej samej
grupie zadan. Ma to pewne zaskakujace konsekwencje w kontekscie
tradycyjnego zachowania wartosci nice w systemach uniksowych. W
szczegolnosci, jesli autogrupowanie jest wlaczone (a tak domyslnie jest
w wielu dystrybucjach), to uzycie setpriority(2) lub nice(1) wobec
procesu odnosi efekt na szeregowaniu tylko wzgledem innych procesow
wykonywanych w tej samej sesji (zwykle: tym samym oknie terminala).
Co za tym idzie, w przypadku dwoch procesow (przykladowo), ktore sa
jedynymi procesami ograniczonymi wydajnoscia procesora, wystepujacych w
dwoch sesjach (np. roznych oknach terminala, zatem kazde z zadan jest
przypisanych do innej autogrupy), modyfikacja wartosc nice procesu w
jednej z sesji nie odnosi skutku wobec decyzji dyspozytora odnoszacej
sie do procesu w drugiej sesji. Przydatnym obejsciem tego
nieintuicyjnego zachowania moze byc polecenie, takie jak ponizsze,
modyfikujace wartosc nice autogrupy wszystkich procesow w sesji
terminala:
$ echo 10 > /proc/self/autogroup
Funkcje czasu rzeczywistego w jadrze Linux z glownej serii
Od Linuksa 2.6.18, Linux jest stopniowo wzbogacany o zdolnosci czasu
rzeczywistego; wiekszosc pochodzi z uprzedniego zestawu latek
realtime-preempt. Latki sa nazywane nastepujaco:
patch-wersjajadra-rtwersjalatki
i mozna je pobrac ze strony lub klonujac drzewo git . Poszczegolne wydania sa
utrzymywane tak dlugo, jak dane jadro LTS.
Od Linuksa 6.12 mozna wlaczyc wywlaszczanie czasu rzeczywistego bez
koniecznosci instalowania latek. realtime-patch wciaz bedzie istnial,
zapewniajac obsluge jeszcze niezintegrowanych architektur, sterownikow
oraz funkcji w trakcie rozwoju.
Od Linux 6.13 mozliwosci czasu rzeczywistego sa zapewniane jako opcja,
a nie model wywlaszczania. Po tej zmianie, dostepne sa nastepujace
modele wywlaszczania: CONFIG_PREEMPT_NONE, CONFIG_PREEMPT_VOLUNTARY,
CONFIG_PREEMPT oraz CONFIG_PREEMPT_LAZY. Mozliwosci czasu rzeczywistego
mozna wlaczyc opcja CONFIG_PREEMPT_RT, a model wywlaszczania mozna
ustawic na CONFIG_PREEMPT lub CONFIG_PREEMPT_LAZY. Ten drugi rzadziej
wywlaszcza zadania SCHED_NORMAL, probujac ograniczyc wywlaszczanie
posiadaczy blokad. Nie ma to wplywu na zadania czasu rzeczywistego.
Po wlaczeniu CONFIG_PREEMPT_RT, Linux staje sie standardowym systemem
operacyjnym czasu rzeczywistego. Algorytmy szeregowania SCHED_FIFO,
SCHED_RR i SCHED_DEADLINE sa wowczas stosowane do uruchamiania watku z
prawdziwym priorytetem czasu rzeczywistego oraz zapewnionym minimalnym
opoznieniem szeregowania najgorszego przypadku.
UWAGI
Do ograniczania uzycia procesora przez grupy procesow mozna stosowac
kontroler procesora cgroups(7).
Pierwotnie, standardowy Linux byl pomyslany jako uniwersalny system
operacyjny, zdolny do obslugi procesow tla, aplikacji interaktywnych
oraz mniej wymagajacych aplikacji czasu rzeczywistego (aplikacji, ktore
zwykle musza miescic sie w ograniczeniach czasowych). Choc Linux 2.6
umozliwil wywlaszczanie przez jadro, a nowo wprowadzony dyspozytor O(1)
zapewnia, ze czas potrzebny na uszeregowanie jest staly i
deterministyczny, niezaleznie od liczby aktywnych zadan, prawdziwe
zachowanie czasu rzeczywistego nie bylo dostepne do Linuksa 2.6.17.
ZOBACZ TAKZE
chcpu(1), chrt(1), lscpu(1), ps(1), taskset(1), top(1), getpriority(2),
mlock(2), mlockall(2), munlock(2), munlockall(2), nice(2),
sched_get_priority_max(2), sched_get_priority_min(2),
sched_getaffinity(2), sched_getparam(2), sched_getscheduler(2),
sched_rr_get_interval(2), sched_setaffinity(2), sched_setparam(2),
sched_setscheduler(2), sched_yield(2), setpriority(2),
pthread_getaffinity_np(3), pthread_getschedparam(3),
pthread_setaffinity_np(3), sched_getcpu(3), capabilities(7), cpuset(7)
Programming for the real world - POSIX.4 autorstwa Billa O.
Gallmeistera, O'Reilly & Associates, Inc., ISBN 1-56592-074-0.
Dokumentacja dyspozytora w jadrze Linux .
Warte przegladniecia na stronie:
TLUMACZENIE
Tlumaczenie niniejszej strony podrecznika: Michal Kulach
Niniejsze tlumaczenie jest wolna dokumentacja. Blizsze informacje o
warunkach licencji mozna uzyskac zapoznajac sie z GNU General Public
License w wersji 3 lub
nowszej. Nie przyjmuje sie ZADNEJ ODPOWIEDZIALNOSCI.
Bledy w tlumaczeniu strony podrecznika prosimy zglaszac na adres listy
dyskusyjnej .
Linux man-pages 6.18 8 lutego 2026 r. sched(7)