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)