DIPLOMSKI RAD br. 1802 RASPOREĐIVANJE POSLOVA U LINUXU · Linux operacijski sustav koristi više...

28
SVEUČILIŠTE U ZAGREBU FAKULTET ELEKTROTEHNIKE I RAČUNARSTVA Zagreb, lipanj 2019. DIPLOMSKI RAD br. 1802 RASPOREĐIVANJE POSLOVA U LINUXU Filip Štimac

Transcript of DIPLOMSKI RAD br. 1802 RASPOREĐIVANJE POSLOVA U LINUXU · Linux operacijski sustav koristi više...

  • SVEUČILIŠTE U ZAGREBU FAKULTET ELEKTROTEHNIKE I RAČUNARSTVA

    Zagreb, lipanj 2019.

    DIPLOMSKI RAD br. 1802

    RASPOREĐIVANJE POSLOVA U LINUXU Filip Štimac

  • i

  • ii

  • iii

    SADRŽAJ

    1. Uvod ............................................................................................................................. 1 2. Raspoređivači poslova ............................................................................................... 2

    2.1. CFS raspoređivač .................................................................................................... 4 2.1.1. pick_next_task_fair .................................................................................................... 4

    2.1.2. pick_next_entity ......................................................................................................... 7

    2.1.3. enqueue_task_fair ....................................................................................................... 7

    2.1.4. dequeue_task_fair ....................................................................................................... 9

    2.1.5. task_fork_fair ............................................................................................................. 9

    2.2. RT raspoređivač .................................................................................................... 10 2.3. Ostali raspoređivači .............................................................................................. 11

    3. Sustav Raspoređivanja poslova .............................................................................. 12 3.1. Inicijalizacija sustava za raspoređivanje poslova ................................................. 12 3.2. Sched_fork ............................................................................................................ 13 3.3. Schedule ................................................................................................................ 14 3.4. Pick_next_task ...................................................................................................... 15

    4. Dodavanje novog raspoređivača ............................................................................. 17 4.1. Priprema ................................................................................................................ 17 4.2. Postavljanje postavki jezgre .................................................................................. 17 4.3. Modificiranje jezgre .............................................................................................. 18

    4.3.1. kernel/sched/fair.c .................................................................................................... 18

    4.3.2. kernel/sched/deadline.c ............................................................................................ 18

    4.3.3. kernel/sched/deadline2.c .......................................................................................... 18

    4.3.4. uapi/linux/sched.h .................................................................................................... 18

    4.3.5. kernel/sched/Makefile .............................................................................................. 19

    4.3.6. Ostale datoteke ......................................................................................................... 19

    4.3.7. Napomena................................................................................................................. 19

    4.4. Instalacija modificirane jezgre .............................................................................. 19 5. Zaključak .................................................................................................................. 21 Literatura ........................................................................................................................... 22 Sažetak ................................................................................................................................ 23 Summary ............................................................................................................................ 23

  • iv

  • 1

    1. UVOD

    Jedan od glavnih dijelova svakog operacijskog sustava je raspoređivač poslova. On je zadužen za određivanje u kojem trenutku će posao, tj. dretva, biti aktivna na procesoru, sortiranju ostalih poslova koji čekaju da ih se dodijeli procesoru, te osiguravanju da svaki posao prije ili kasnije bude izvršen u ovisnosti o prioritetu. Ovaj rad je napravljen u svrhu istraživanja načina raspoređivanja poslova u Linux operacijskom sustavu. Linux operacijski sustav je kroz vrijeme prošao kroz nekoliko iteracija sustava za raspoređivanje poslova. U istraživanju Linux raspoređivača poslova naglasak je stavljen na izvorni kod operacijskog sustava. Uz kod, proučavanje sustava za raspoređivanje poslova napravit će se dodavanjem novog raspoređivača u jezgru Linuxa. Dodavanje novog raspoređivača pruža alternativni pogled na sustav za raspoređivanje, gdje se uz opisivanje procesa dodavanja ujedno i prikazuje povezanost samog sustava s pojedinačnim raspoređivačem Rad je podijeljen u pet poglavlja. U drugom poglavlju opisuju se različiti raspoređivači s naglaskom na CFS raspoređivač. Treće poglavlje daje pogled na sustav za raspoređivanje poslova i kako on koristi implementirane raspoređivače. U četvrtom poglavlju opisan je postupak dodavanja novog raspoređivača u jezgru Linuxa. Peto poglavlje sadrži zaključak.

  • 2

    2. RASPOREĐIVAČI POSLOVA

    Linux operacijski sustav koristi više vrsta raspoređivača poslova, gdje svaki ima određenu skupinu poslova koja je najprikladnija za tog raspoređivača. Rad kao referencu koristi Linux jezgru verzije v5.0.0 [1]. Raspoređivači poslova sadrže zajedničke koncepte, koje implementiraju na različite načine. Svaki raspoređivač ima svoj red pripravnih poslova u kojem sprema poslove i iz kojeg uzima novi posao za postaviti na procesor i ima određen postupak na koji odabire taj zadatak [2]. Raspoređivači se mogu posložiti po prioritetu od najvišeg prema najnižem prioritetu, gdje:

    • STOP raspoređivač je namijenjen za zaustavljanje procesora, • DEADLINE za periodičke poslove s vremenskim rokom, • RT druga implementacija namijenjena za periodičke poslove s vremenskim rokom, • CFS (Completely fair scheduler) za standardne poslove u sustavu i poslove niskog

    prioriteta i • IDLE raspoređivač namijenjen za održavanje aktivnosti procesora u trenutku kad

    nema korisnih poslova. Svaki od gore navedenih raspoređivača implementira sučelje sched_class, koje definira glavne funkcije raspoređivača poslova. Tako se osigurava konzistentnost u korištenju različitih vrsta raspoređivača unutar sustava. Sučelje sched_class prikazano je u isječku koda (Isječak koda 2.1). Pokazivač next pokazuje na sljedeći raspoređivač poslova nižeg prioriteta. S povezivanjem raspoređivača u povezanu listu pomoću tog pokazivača dobiva se jednostavan način za prolazak po prioritetu kroz sve raspoređivače.

    Isječak koda 2.1. /kernel/sched/sched.h sched_class sučelje 1630 struct sched_class {

    1631 const struct sched_class *next;

    1632

    1633 void (*enqueue_task) (struct rq *rq, struct task_struct *p,

    int flags);

    1634 void (*dequeue_task) (struct rq *rq, struct task_struct *p,

    int flags);

    1635 void (*yield_task) (struct rq *rq);

    1636 bool (*yield_to_task)(struct rq *rq, struct task_struct *p,

    bool preempt);

    1637

    1638 void (*check_preempt_curr)(struct rq *rq, struct task_struct *p,

    int flags);

    ....

    1648 struct task_struct * (*pick_next_task)(

    struct rq *rq,

    1649 struct task_struct *prev,

    1650 struct rq_flags *rf);

    1651 void (*put_prev_task)(struct rq *rq, struct task_struct *p);

    1652

    1653 #ifdef CONFIG_SMP

    1654 int (*select_task_rq)(struct task_struct *p, int task_cpu,

    int sd_flag, int flags);

    1655 void (*migrate_task_rq)(struct task_struct *p, int new_cpu);

    1656

    1657 void (*task_woken)(struct rq *this_rq,

    struct task_struct *task);

    1658

    1659 void (*set_cpus_allowed)(struct task_struct *p,

  • 3

    1660 const struct cpumask *newmask);

    1661

    1662 void (*rq_online)(struct rq *rq);

    1663 void (*rq_offline)(struct rq *rq);

    1664 #endif

    1665

    1666 void (*set_curr_task)(struct rq *rq);

    1667 void (*task_tick)(struct rq *rq, struct task_struct *p,

    int queued);

    1668 void (*task_fork)(struct task_struct *p);

    1669 void (*task_dead)(struct task_struct *p);

    1670

    ....

    1676 void (*switched_from)(struct rq *this_rq,

    struct task_struct *task);

    1677 void (*switched_to) (struct rq *this_rq,

    struct task_struct *task);

    1678 void (*prio_changed) (struct rq *this_rq,

    struct task_struct *task,

    1679 int oldprio);

    1680

    1681 unsigned int (*get_rr_interval)(struct rq *rq,

    1682 struct task_struct *task);

    1683

    1684 void (*update_curr)(struct rq *rq);

    1685

    1686 #define TASK_SET_GROUP 0

    1687 #define TASK_MOVE_GROUP 1

    1688

    1689 #ifdef CONFIG_FAIR_GROUP_SCHED

    1690 void (*task_change_group)(struct task_struct *p, int type);

    1691 #endif

    1692 };

    Glavne funkcije sched_class razreda su:

    • enqueue_task - dodaje novi posao u red pripravnih dretvi, • dequeue_task - skida posao iz reda pripravnih dretvi, • yield_task – skida trenutno aktivni posao s procesora, stavlja ga u red pripravnih

    dretvi i mijenja s drugim zadatkom. • pick_next_task - vraća posao koji bi trenutno trebao biti aktivan, • update_curr - osvježava statistiku o trenutnom poslu i • task_fork – provodi inicijalizacijski postupak za novo stvoreni posao.

    Životni ciklus posla može se pratiti kroz naredbe u sched_class. U početku se kreira novi posao, te se za njegov postavljeni raspoređivač zove task_fork()s kojim se on postavlja na čekanje u red pripravnih dretvi toga raspoređivača. U slučaju promjene prioriteta posla poziva se prio_changed() funkcija, koja osvježava trenutnu poziciju posla u redu pripravnih poslova ovisno o novom prioritetu. Ako se promijeni raspoređivač koji je zadužen za taj posao, na starom raspoređivaču se poziva funkcija switched_from(), koja taj posao skida sa svog reda pripravnih poslova i poziva se funkcija switched_to() na novom raspoređivaču koji će taj posao staviti u svoj red pripravnih poslova. U nekom trenutku posao će biti najvišeg prioriteta za postavljanje na procesor, pa će prilikom sljedećeg poziva pick_next_task() biti odabran i postavljen pa procesor. U slučaju da se posao treba zablokirati, dok čeka nove podatke, pozvat će se funkcija yield_task() koja će uzeti novi posao za postaviti na procesor. U nekom trenutku će posao završiti, prilikom čega će se pozvati funkcija task_dead(), koja će ga maknuti iz reda pripravnih poslova.

  • 4

    2.1. CFS raspoređivač

    CFS raspoređivač je trenutna implementacija raspoređivača dretvi za općenite poslove u sustavu. U Linux ljusku je ugrađen 13. travnja 2007 godine. Njegove glavne značajke su korištenje crveno-crna stabla za red pripravnih poslova, smanjenje vremenske zrnatosti na nanosekunde i povećanje utjecaja vrijednosti dobrote na prioritete poslova [6]. Poslovi su postavljeni u crveno-crna stablo, gdje svaki posao dobiva vrijeme kad će doći na procesor, ovisno o njegovom prioritetu. Zbog činjenice da su crveno-crna stabla samobalansirajuća, sljedeći proces se dobiva uzimanjem najljevijeg čvora u stablu, jer će on zbog tog svojstva imati najmanje definirano vrijeme. Prilikom vraćanja aktivnog posla u stablo, njemu se dodaje određena količina vremena ovisno o njegovom prioritetu, kako bi i drugim poslovima omogućio da dođu do procesora. CFS ima podršku za cgrupe. Cgrupa je skup poslova koji može imati ograničenja na pristup određenim procesorima i veličini potrošnje memorije [3, 6]. One omogućuju bolju raspodjelu procesorskog vremena. Npr. ako postoji jedna grupa s tri posla i drugu grupu s dva posla istih prioriteta, raspoređivač će i jednoj i drugoj grupi dodijeliti 50% procesorskog vremena. Prva grupa će dobivenih 50% procesorskog vremena podijeliti između tri posla, dok će druga grupa dobivenih 50% procesorskog vremena podijeliti između dva posla. Cgrupe dozvoljavaju ulančavanje, gdje neka grupa u sebi može sadržavati neku drugu grupu.

    2.1.1. pick_next_task_fair Funkcija koja odabire posao koji će se sljedeći staviti na proces. Funkciju se može podijeliti na tri dijela. Ako u redu pripravnih poslova nema novih poslova (Isječak koda 2.2:7017), poziva se idle_balance() funkcija, koja pokušava od drugih procesora preuzeti dio poslova iz njihovih redova pripravnih poslova. Ako su uspješno preuzeti novi poslovi, funkcija kreće iz početka.

    Isječak koda 2.2: kernel/sched/fair.c Funkcija za odabir sljedećeg posla u CFS-u 1. dio 6897 static struct task_struct *

    6898 pick_next_task_fair(struct rq *rq, struct task_struct *prev,

    struct rq_flags *rf)

    6899 {

    ...

    6905 again:

    6906 if (!cfs_rq->nr_running)

    6907 goto idle;

    ...

    7015 idle:

    7016 update_misfit_status(NULL, rq);

    7017 new_tasks = idle_balance(rq, rf);

    ...

    7024 if (new_tasks < 0)

    7025 return RETRY_TASK;

    7026

    7027 if (new_tasks > 0)

    7028 goto again;

    7029

    7030 return NULL;

    7031 }

  • 5

    Ako prethodni posao ne pripada CFS raspoređivaču, funkcija skače na jednostavni postupka uzimanja sljedećeg posla. Poziva pick_next_entity() funkciju dok ne prođe kroz sve cgrupe i dođe do sljedećeg posla (Isječak koda 2.3:6988 - : 6996), kojeg nakon toga vraća.

    Isječak koda 2.3.: kernel/sched/fair.c Funkcija za odabir sljedećeg posla u CFS-u 2. dio 6897 static struct task_struct *

    6898 pick_next_task_fair(struct rq *rq, struct task_struct *prev,

    struct rq_flags *rf)

    6899 {

    ...

    6909 #ifdef CONFIG_FAIR_GROUP_SCHED

    6910 if (prev->sched_class != &fair_sched_class)

    6911 goto simple;

    ...

    6985 simple:

    6986 #endif

    6987

    6988 put_prev_task(rq, prev);

    6989

    6990 do {

    6991 se = pick_next_entity(cfs_rq, NULL);

    6992 set_next_entity(cfs_rq, se);

    6993 cfs_rq = group_cfs_rq(se);

    6994 } while (cfs_rq);

    6995

    6996 p = task_of(se);

    6997

    6998 done: __maybe_unused;

    ...

    7005 list_move(&p->se.group_node, &rq->cfs_tasks);

    7006 #endif

    ...

    7013 return p;

    ...

    7031 }

    Inače ako prethodni posao pripada CFS raspoređivaču nastoji se izbjeći prolaz kroz cijelu grupu poslova, prilikom traženja novog posla, nego se pomoću trenutno aktivnog posla nastoji pronaći sljedeći posao (Isječak koda 2.4. :6921 - :6956).

    Isječak koda 2.4.: kernel/sched/fair.c Funkcija za odabir sljedećeg posla u CFS-u 6897 static struct task_struct *

    6898 pick_next_task_fair(struct rq *rq, struct task_struct *prev,

    struct rq_flags *rf)

    6899 {

    ...

    6921 do {

    6922 struct sched_entity *curr = cfs_rq->curr;

    ...

    6930 if (curr) {

    6931 if (curr->on_rq)

    6932 update_curr(cfs_rq);

    6933 else

    6934 curr = NULL;

    ...

    6942 if (unlikely(check_cfs_rq_runtime(cfs_rq))) {

    6943 cfs_rq = &rq->cfs;

  • 6

    6944

    6945 if (!cfs_rq->nr_running)

    6946 goto idle;

    6947

    6948 goto simple;

    6949 }

    6950 }

    6951

    6952 se = pick_next_entity(cfs_rq, curr);

    6953 cfs_rq = group_cfs_rq(se);

    6954 } while (cfs_rq);

    6955

    6956 p = task_of(se);

    ...

    6963 if (prev != p) {

    6964 struct sched_entity *pse = &prev->se;

    6965

    6966 while (!(cfs_rq = is_same_group(se, pse))) {

    6967 int se_depth = se->depth;

    6968 int pse_depth = pse->depth;

    6969

    6970 if (se_depth = pse_depth) {

    6975 set_next_entity(cfs_rq_of(se), se);

    6976 se = parent_entity(se);

    6977 }

    6978 }

    6979

    6980 put_prev_entity(cfs_rq, pse);

    6981 set_next_entity(cfs_rq, se);

    6982 }

    6983

    6984 goto done;

    6985 simple:

    6986 #endif

    6987

    6988 put_prev_task(rq, prev);

    6989

    6990 do {

    6991 se = pick_next_entity(cfs_rq, NULL);

    6992 set_next_entity(cfs_rq, se);

    6993 cfs_rq = group_cfs_rq(se);

    6994 } while (cfs_rq);

    6995

    6996 p = task_of(se);

    6997

    6998 done: __maybe_unused;

    ...

    7005 list_move(&p->se.group_node, &rq->cfs_tasks);

    7006 #endif

    ...

    7013 return p;

    ...

    7031 }

  • 7

    2.1.2. pick_next_entity Funkcija koja bira posao između dobivenog posla i postavljenih drugova (engl buddy). CFS raspoređivač za vrijeme izvođenja prati i postavlja drugove. Drugovi su privremeno označeni poslovi. Postoje tri vrste drugova:

    • skip ako postoje drugi poslovi u redu pripravnih poslova ovaj posao se preskače, • last ako je ovaj posao bio zadnji probaj ga odabrati i • next netko želi ovaj posao da se izvrši pa ga probaj odabrati.

    Privremene oznake drugova se brišu na kraju ove funkcije pozivom clear_buddies(). Iz isječka koda (Isječak koda 2.5.:4138 - :4145) može se vidjeti ako će se i last i next posao biti odabrani na kraju će biti odabran next posao.

    Isječak koda 2.5.: Pick_next_entity funkcija s prikazanim drugovima 4101 static struct sched_entity *

    4102 pick_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *curr)

    4103 {

    4104 struct sched_entity *left = __pick_first_entity(cfs_rq);

    4105 struct sched_entity *se;

    ...

    4111 if (!left || (curr && entity_before(curr, left)))

    4112 left = curr;

    4113

    4114 se = left;

    ...

    4120 if (cfs_rq->skip == se) {

    4121 struct sched_entity *second;

    4122

    4123 if (se == curr) {

    4124 second = __pick_first_entity(cfs_rq);

    4125 } else {

    4126 second = __pick_next_entity(se);

    4127 if (!second ||

    (curr && entity_before(curr, second)))

    4128 second = curr;

    4129 }

    4130

    4131 if (second && wakeup_preempt_entity(second, left) < 1)

    4132 se = second;

    4133 }

    ...

    4138 if (cfs_rq->last &&

    wakeup_preempt_entity(cfs_rq->last, left) < 1)

    4139 se = cfs_rq->last;

    ...

    4144 if (cfs_rq->next &&

    wakeup_preempt_entity(cfs_rq->next, left) < 1)

    4145 se = cfs_rq->next;

    4146

    4147 clear_buddies(cfs_rq, se);

    4148

    4149 return se;

    4150 }

    2.1.3. enqueue_task_fair Funkcija koja se poziva kad se novi posao dodaje u raspoređivač. U prvom dijelu funkcije osvježava se generalna statistika sustava. Nakon toga se dodaje novi posao u red pripravnih

  • 8

    poslova (Isječak koda 2.6.:5130 - :5146), gdje se poziva enqueue_entity(). U enqueue_entity() se računa zauzeće grupe u koju se stavlja novi posao i posao se dodaje u red pripravnih poslova. U zadnjem koraku povećava se h_nr_running koji predstavlja broj trenutnih poslova u CFS redu pripravnih poslova i ponovno se osvježava zauzeće grupe (Isječak koda 2.6.:5156) i podjela poslova unutar te grupe (Isječak koda 2.6.:5157).

    Isječak koda 2.6.: kernel/sched/fair.c Enqueue_task_fair funkcija 5108 static void

    5109 enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)

    5110 {

    5111 struct cfs_rq *cfs_rq;

    5112 struct sched_entity *se = &p->se;

    ...

    5120 util_est_enqueue(&rq->cfs, p);

    5121

    ...

    5127 if (p->in_iowait)

    5128 cpufreq_update_util(rq, SCHED_CPUFREQ_IOWAIT);

    5129

    5130 for_each_sched_entity(se) {

    5131 if (se->on_rq)

    5132 break;

    5133 cfs_rq = cfs_rq_of(se);

    5134 enqueue_entity(cfs_rq, se, flags);

    ...

    5142 if (cfs_rq_throttled(cfs_rq))

    5143 break;

    5144 cfs_rq->h_nr_running++;

    5145

    5146 flags = ENQUEUE_WAKEUP;

    5147 }

    5148

    5149 for_each_sched_entity(se) {

    5150 cfs_rq = cfs_rq_of(se);

    5151 cfs_rq->h_nr_running++;

    5152

    5153 if (cfs_rq_throttled(cfs_rq))

    5154 break;

    5155

    5156 update_load_avg(cfs_rq, se, UPDATE_TG);

    5157 update_cfs_group(se);

    5158 }

    5159

    5160 if (!se) {

    5161 add_nr_running(rq, 1);

    ...

    5179 }

    5180

    5181 hrtick_update(rq);

    5182 }

  • 9

    2.1.4. dequeue_task_fair Funkcija koja se poziva kada se posao uklanja iz reda pripravnih poslova. Semantički suprotna, ali implementacijski slična funkciji enqueue_task_fair. Izvršava niz poslova:

    • osvježava statistiku, • uklanja posao iz grupe i redova pripravnih poslova, • briše za taj posao označene drugove, • smanjuje h_nr_running • i osvježava statistiku za grupu kojoj je posao pripadao.

    2.1.5. task_fork_fair Funkcija koja se poziva na novo stvorenom poslu. Zadužena je za postavljanje početnog vremena novo stvorenom poslu (Isječak koda 2.7.:10064 - :10077), prema kojem će taj posao biti uspoređivan u trenutku stavljanja u red pripravnih poslova. Prije nego što započne s čitanjem podataka potrebno je zaključati red pripravnih poslova, kako ne bi došlo do problema s čitanjem i mijenjanjem podataka, te nakon što se postavi vrijeme novom poslu potrebno je otključati red pripravnih poslova. U slučaju kad se dijete pokreće prije roditelja i vremenski je prije njega, potrebno je zamijeniti njihova spremljena vremena i pozvati resched_curr() (Isječak koda 2.7.:10070 - :10077).

    Isječak koda 2.7.: kernel/sched/fair.c task_fork_fair funkcija 10052 static void task_fork_fair(struct task_struct *p)

    10053 {

    10054 struct cfs_rq *cfs_rq;

    10055 struct sched_entity *se = &p->se, *curr;

    10056 struct rq *rq = this_rq();

    10057 struct rq_flags rf;

    10058

    10059 rq_lock(rq, &rf);

    10060 update_rq_clock(rq);

    10061

    10062 cfs_rq = task_cfs_rq(current);

    10063 curr = cfs_rq->curr;

    10064 if (curr) {

    10065 update_curr(cfs_rq);

    10066 se->vruntime = curr->vruntime;

    10067 }

    10068 place_entity(cfs_rq, se, 1);

    10069

    10070 if (sysctl_sched_child_runs_first && curr &&

    entity_before(curr, se)) {

    ...

    10075 swap(curr->vruntime, se->vruntime);

    10076 resched_curr(rq);

    10077 }

    10078

    10079 se->vruntime -= cfs_rq->min_vruntime;

    10080 rq_unlock(rq, &rf);

    10081 }

  • 10

    2.2. RT raspoređivač

    RT raspoređivač napravljen je za raspoređivanje poslova koji se izvode u stvarnom vremenu. Takvi poslovi su višeg prioriteta od CFS raspoređivača, te oni trebaju što prije biti izvršeni u sustavu. Sadrži implementacije SCHED_FIFO i SCHED_RR načina raspoređivanja. U FIFO implementaciji poslovi će se obrađivati redoslijedom kojim dolaze, i na procesoru će ostati sve dok se ne završe ili dok ne dođe posao višeg prioriteta. RR implementacija dijeli procesorsko vrijeme svim poslovima unutar jednog prioriteta u krug, gdje kao i kod FIFO implementacije u slučaju postojanja više skupina s različitim prioritetima, svo procesorsko vrijeme će pripasti onoj grupi s višim prioritetom. RT raspoređivač prilikom inicijalizacije stvara MAX_RT_PRIO listi prioriteta (Isječak koda 2.8.). Redovi prioriteta su implementirani dvostruko povezanim listama, zbog čega je implementacija dodavanja i skidanja iz reda prioriteta jednostavna.

    Isječak koda 2.8.: /kernel/sched/rt.c Inicijalizacijska funkcija RT raspoređivača 75 void init_rt_rq(struct rt_rq *rt_rq)

    76 {

    77 struct rt_prio_array *array;

    78 int i;

    79

    80 array = &rt_rq->active;

    81 for (i = 0; i < MAX_RT_PRIO; i++) {

    82 INIT_LIST_HEAD(array->queue + i);

    83 __clear_bit(i, array->bitmap);

    84 }

    85 /* delimiter for bitsearch: */

    86 __set_bit(MAX_RT_PRIO, array->bitmap);

    87

    88 #if defined CONFIG_SMP

    89 rt_rq->highest_prio.curr = MAX_RT_PRIO;

    90 rt_rq->highest_prio.next = MAX_RT_PRIO;

    91 rt_rq->rt_nr_migratory = 0;

    92 rt_rq->overloaded = 0;

    93 plist_head_init(&rt_rq->pushable_tasks);

    94 #endif /* CONFIG_SMP */

    95 /* We start is dequeued state, because no RT tasks are queued */

    96 rt_rq->rt_queued = 0;

    97

    98 rt_rq->rt_time = 0;

    99 rt_rq->rt_throttled = 0;

    100 rt_rq->rt_runtime = 0;

    101 raw_spin_lock_init(&rt_rq->rt_runtime_lock);

    102 }

  • 11

    2.3. Ostali raspoređivači

    STOP raspoređivač je raspoređivač najvišeg prioriteta. Posao postavljen na njega se ne skida s procesora. Koristi se za zaustavljanje procesora. IDLE raspoređivač je raspoređivač najnižeg prioriteta. Posao postavljen na njemu nikad ne dolazi na procesor dok god postoje drugi poslovi u sustavu. Njemu se prilikom inicijalizacije operacijskog sustava dodjeljuje idle posao, čiji je zadatak da radi ništa, te da bude postavljen na procesor samo onda kad on nema drugih poslova za uzeti. DEADLINE raspoređivač napravljen je za raspoređivanje poslova koji se vrte u stvarnom vremenu. Poslovi koji se periodički vrte kraće od njihovog postavljenog vremena izvođenja neće propustiti svoj vremenski rok za izvršavanje [4]. Za red pripravnih poslova koristi se crveno-crna stablo. Postavljeni poslovi definiraju svoje očekivano trajanje i vremenski rok do kad trebaju biti izvršeni.

  • 12

    3. SUSTAV RASPOREĐIVANJA POSLOVA

    Cilj svakog raspoređivanja poslova u operacijskom sustavu je pravedno podijeliti procesorsko vrijeme svim poslovima, tj. dretvama kako bi svi poslovi uspješno završili sa svojim radom, te dodatno i osigurati interaktivnost sustava. Interaktivnost se može opisati kao korisnička interakcija sa sustavom, gdje je visoka interaktivnost kad korisnik ima dojam da je trenutni program koji koristi "glavni", tj. da se korisničke akcije na tom sustavu izvrše maksimalno brzo ili da se ne primjećuje prekidi u radu programa. Primjer bi bilo slušanje glazbe u pozadini, gdje bi niska interaktivnost predstavljala primjetne prekide u reproduciranju glazbe.

    3.1. Inicijalizacija sustava za raspoređivanje poslova

    Zadatak inicijalizacije je osigurati da su pripremljene sve strukture potrebne za rad raspoređivača poslova u sustavu. Svaki procesor dobiva svoje vlastite redove pripravnih poslova za svaki od implementiranih raspoređivača. Inicijalizacija se započinje prilikom pokretanja operacijskog sustava. Za svaki procesor stvaraju se i inicijaliziraju redovi pripravnih poslova raspoređivača (Isječka koda 3.1.:5989 - :6060), posao koji izvršava ove naredbe postavlja se u stanje IDLE (Isječak koda 3.1.:6076), postavlja se propusnost pojedinih raspoređivača (Isječak koda 3.1.:5868-:5969), i na kraju se postavlja zastavica running, koja obavještava ostatak sustava da je sustav raspoređivača gotov s inicijalizacijom. Predodređene maksimalne vrijednosti propusnosti za RT i DEADLINE raspoređivače su oko 95% vremena na procesoru, što osigurava da ostane dovoljno rezervnog procesorskog vremena kako bi se ručno mogao ugasiti posao visokog prioriteta u slučaju kad dođe do greške, npr. uđe u beskonačnu petlju i zauzme cijelo vrijeme na procesoru.

    Isječak koda 3.1.: /kernel/sched/core.c Inicijalizacija raspoređivača poslova 5926 void __init sched_init(void)

    5927 {

    ...

    5967

    5968 init_rt_bandwidth(&def_rt_bandwidth, global_rt_period(),

    global_rt_runtime());

    5969 init_dl_bandwidth(&def_dl_bandwidth, global_rt_period(),

    global_rt_runtime());

    ...

    5989 for_each_possible_cpu(i) {

    5990 struct rq *rq;

    5991

    5992 rq = cpu_rq(i);

    5993 raw_spin_lock_init(&rq->lock);

    5994 rq->nr_running = 0;

    5995 rq->calc_load_active = 0;

    5996 rq->calc_load_update = jiffies + LOAD_FREQ;

    5997 init_cfs_rq(&rq->cfs);

    5998 init_rt_rq(&rq->rt);

    5999 init_dl_rq(&rq->dl);

    6000 #ifdef CONFIG_FAIR_GROUP_SCHED

    6001 root_task_group.shares = ROOT_TASK_GROUP_LOAD;

    6002 INIT_LIST_HEAD(&rq->leaf_cfs_rq_list);

    6003 rq->tmp_alone_branch = &rq->leaf_cfs_rq_list;

    ...

  • 13

    6023 init_cfs_bandwidth(&root_task_group.cfs_bandwidth);

    6024 init_tg_cfs_entry(&root_task_group, &rq->cfs, NULL, i,

    NULL);

    6025 #endif /* CONFIG_FAIR_GROUP_SCHED */

    6026

    6027 rq->rt.rt_runtime = def_rt_bandwidth.rt_runtime;

    6028 #ifdef CONFIG_RT_GROUP_SCHED

    6029 init_tg_rt_entry(&root_task_group, &rq->rt, NULL, i,

    NULL);

    6030 #endif

    6032 for (j = 0; j < CPU_LOAD_IDX_MAX; j++)

    6033 rq->cpu_load[j] = 0;

    ...

    6060 }

    ...

    6076 init_idle(current, smp_processor_id());

    6077

    6078 calc_load_update = jiffies + LOAD_FREQ;

    6079

    6080 #ifdef CONFIG_SMP

    6081 idle_thread_set_boot_cpu();

    6082 #endif

    6083 init_sched_fair_class();

    6084

    6085 init_schedstats();

    6086

    6087 psi_init();

    6088

    6089 scheduler_running = 1;

    6090 }

    3.2. Sched_fork

    Novi posao u Linux operacijskom sustavu stvara se koristeći sistemsku funkcija fork(), koja kreira kopiju konteksta posla iz predanog roditelja, te toj kopiji prosljeđuje njen sljedeći posao. U funkciji fork() u jednom trenutku dolazi do poziva funkcije sched_fork(), koja inicijalizira podatke za raspoređivanje za novi posao (kopiju roditelja). Novi posao, u slučaju da to nije dodatno označeno zastavicom SCHED_RESET_ON_FORK bit će istog prioriteta i koristi isti raspoređivač kao i njen roditelj, kao što se može vidjeti u izvornom kodu (Isječak koda 3.2.:2331-:2347), u protivnom će biti postavljen na pretpostavljene vrijednosti. Nakon toga posao će se dodati u red pripravnih poslova na postavljeni raspoređivač pozivom funkcije task_fork(), u izvornom kodu (Isječak koda 3.2.:2371 - :2372).

    Isječak koda 3.2.: /kernel/sched/core.c Inicijalizacija raspoređivača za novi posao 2311 int sched_fork(unsigned long clone_flags, struct task_struct *p)

    2312 {

    2313 unsigned long flags;

    2314

    2315 __sched_fork(clone_flags, p);

    ...

    2321 p->state = TASK_NEW;

    ...

    2326 p->prio = current->normal_prio;

    ...

    2331 if (unlikely(p->sched_reset_on_fork)) {

    2332 if (task_has_dl_policy(p) || task_has_rt_policy(p)) {

  • 14

    2333 p->policy = SCHED_NORMAL;

    2334 p->static_prio = NICE_TO_PRIO(0);

    2335 p->rt_priority = 0;

    2336 } else if (PRIO_TO_NICE(p->static_prio) < 0)

    2337 p->static_prio = NICE_TO_PRIO(0);

    2338

    2339 p->prio = p->normal_prio = __normal_prio(p);

    2340 set_load_weight(p, false);

    ...

    2346 p->sched_reset_on_fork = 0;

    2347 }

    2348

    2349 if (dl_prio(p->prio))

    2350 return -EAGAIN;

    2351 else if (rt_prio(p->prio))

    2352 p->sched_class = &rt_sched_class;

    2353 else

    2354 p->sched_class = &fair_sched_class;

    2355

    2356 init_entity_runnable_average(&p->se);

    ...

    2370 __set_task_cpu(p, smp_processor_id());

    2371 if (p->sched_class->task_fork)

    2372 p->sched_class->task_fork(p);

    ...

    2388 }

    3.3. Schedule

    Schedule je glavna funkcija kod raspoređivanja poslova. Zadužena je za mijenjanje trenutno aktivnog posla na procesoru. Ona se poziva u slučaju kad se trenutno aktivna dretva zablokira ili kad se postavi zastavica TIF_NEED_RESCHED koja signalizira da je vrijeme za promjenu aktivnog posla. TIF_NEED_RESCHED se postavlja periodički u funkciji scheduler_tick() ili pozivom funkcije check_preempt_curr() kad se uspostavi da postoji posao višeg prioriteta [7]. Schedule funkcija izvršava sljedeće korake:

    • dohvatiti trenutno aktivni posao (Isječak koda 3.3.:3405), • zaključati red pripravnih poslova (Isječak koda 3.3.:3423), • pronaći sljedeći posao pozivom funkcije pick_next_task() (Isječak koda

    3.3.:3459), • resetirati zastavice (Isječak koda 3.3.:3460 - :3461) i • na kraju promijeniti trenutni kontekst na novo pronađeni posao pozivom funkcije

    context_switch() koja ujedno i otključava red pripravnih poslova. (Isječak koda 3.3.:3485)

    Isječak koda 3.3.: /kernel/sched/core.c Schedule funkcija 3395 static void __sched notrace __schedule(bool preempt)

    3396 {

    ...

    3403 cpu = smp_processor_id();

    3404 rq = cpu_rq(cpu);

    3405 prev = rq->curr;

    3406

    3407 schedule_debug(prev);

    3408

    3409 if (sched_feat(HRTICK))

  • 15

    3410 hrtick_clear(rq);

    3411

    3412 local_irq_disable();

    3413 rcu_note_context_switch(preempt);

    3414

    ...

    3423 rq_lock(rq, &rf);

    3424 smp_mb__after_spinlock();

    3425

    3426 /* Promote REQ to ACT */

    3427 rq->clock_update_flags curr = next;

    ...

    3480 ++*switch_count;

    3481

    3482 trace_sched_switch(preempt, prev, next);

    3483

    3484 /* Also unlocks the rq: */

    3485 rq = context_switch(rq, prev, next, &rf);

    3486 } else {

    3487 rq->clock_update_flags &=

    ~(RQCF_ACT_SKIP|RQCF_REQ_SKIP);

    3488 rq_unlock_irq(rq, &rf);

    3489 }

    3490

    3491 balance_callback(rq);

    3492 }

    3.4. Pick_next_task

    U pick_next_task() funkciji nalazi se logika za odabir sljedećeg aktivnog posla. Njen cilj je proći kroz sve raspoređivače i pronaći posao najvišeg prioriteta. Kako je glavni raspoređivač u sustav CFS, napravljena je dodatna optimizacija kako bi se brže dohvatio sljedeći posao iz tog raspoređivača, u slučaju kad svi trenutno živi poslovi, a i prijašnji (trenutno aktivni) posao pripadaju navedenom raspoređivaču, kao što se može vidjeti u isječku koda(Isječak koda 3.4.:3327 - :3339). Ako taj uvjet nije zadovoljen, funkcija prolazi kroz sve raspoređivače redom po prioritetu, i traži prvi raspoređivač koji će vratiti sljedeći posao (Isječak koda 3.4.:3343 - :3350). Sustav garantira da će uvijek naći sljedeći posao. To je osigurano pomoću raspoređivača IDLE (raspoređivač s najnižim prioritetom) koji u sebi sadrži uvijek spreman posao, koji ima praznu implementaciju.

    Isječak koda 3.4.: kernel/sched/code.c Pick_next_task funkcija za odabir sljedećeg aktivnog posla 3315 static inline struct task_struct *

    3316 pick_next_task(struct rq *rq, struct task_struct *prev,

    struct rq_flags *rf)

    3317 {

    3318 const struct sched_class *class;

    3319 struct task_struct *p;

  • 16

    ...

    3327 if (likely((prev->sched_class == &idle_sched_class ||

    3328 prev->sched_class == &fair_sched_class) &&

    3329 rq->nr_running == rq->cfs.h_nr_running)) {

    3330

    3331 p = fair_sched_class.pick_next_task(rq, prev, rf);

    3332 if (unlikely(p == RETRY_TASK))

    3333 goto again;

    ...

    3336 if (unlikely(!p))

    3337 p = idle_sched_class.pick_next_task(rq, prev,

    rf);

    3338

    3339 return p;

    3340 }

    3341

    3342 again:

    3343 for_each_class(class) {

    3344 p = class->pick_next_task(rq, prev, rf);

    3345 if (p) {

    3346 if (unlikely(p == RETRY_TASK))

    3347 goto again;

    3348 return p;

    3349 }

    3350 }

    ...

    3354 }

  • 17

    4. DODAVANJE NOVOG RASPOREĐIVAČA

    Cilj dodavanja novog raspoređivača u Linux operacijski sustav u ovom radu je kako bi se pokazao postupak kroz koji je potrebno proći kako bi se dodao novi raspoređivač, ali i promijenile funkcije trenutnih raspoređivača, te da se pruži pregled glavnih mjesta gdje je potrebno napraviti promjene za uspješan rad novo dodanog raspoređivača. Novi raspoređivač je kopija DEADLINE raspoređivača, gdje je svaka struktura, funkcija i varijabla preimenovana dodavanjem broja 2. Npr. sched_dl_global_validate() je preimenovana u sched_dl2_global_validate(). Tako se novi raspoređivač osigurava da neće slučajno koristiti strukture, funkcije ili varijable trenutnog DEADLINE raspoređivača. Novi raspoređivač će biti nižeg prioriteta od trenutno raspoređivača. Modifikacije Linux jezgre napravljene su na Ubuntu operacijskom sustavu verzije 19.04. Za kompajliranje jezgre Linuxa korištene su upute s bloga [7].

    4.1. Priprema

    Potrebno je instalirati dodatne alate, prije nego što se započne s mijenjanjem Linux jezgre. Alati su instalirani koristeći Ubuntove repozitorije, s naredbom: sudo apt install install git build-essential kernel-package fakeroot

    libncurses5-dev libssl-dev ccache

    Sljedeći korak je dohvaćanje verzije jezgre na kojoj će se provoditi modifikacije. Prije preuzimanja potrebno se pozicionirati u direktorij u kojem će se spremiti dobivena jezgra. U ovom radu korištena je v5.0.0 verzija Linux jezgre preuzeta s git repozitorija i skinuta je u datoteku /usr/src/kernelbuild s naredbama: cd /usr/src

    mkdir kernelbuild

    cd kernelbuild

    git clone –b linux-5.0.y \

    git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git

    4.2. Postavljanje postavki jezgre

    Zbog jednostavnosti preuzeta jezgra će koristiti iste postavke kao i postojeća jezgra u sustavu. Potrebno je iskopirati postavke postojeće jezgre i odabrati aktivne dodatke (engl. features) u sustavu. cd linux

    cp /boot/config-`uname -r` .config

    Moguće je automatsko dodavanje svih dodataka u postavkama. yes '' | make oldconfig

    U slučaju da se žele odabrati i/ili isključiti određeni dodatci može se koristiti naredba make oldconfig.

    Dodatne opcije u jezgri se mogu podesiti koristeći naredbu make menuconfig.

  • 18

    4.3. Modificiranje jezgre

    Jezgru Linuxa će se modificirati dodavanjem novog raspoređivača. Prvi korak je kopiranje i preimenovanje trenutnog raspoređivača kernel/sched/deadline.c u deadline2.c. i include/linux/sched/deadline.h u deadline2.h. Nakon toga potrebno je postupno preimenovati imena struktura, funkcija i varijabli. Kako bi se novi raspoređivač mogao koristiti u sustavu, potrebno je napraviti niz modifikacija po kodu kako bi se on integrirao u sustav. Većina modifikacija je dupliciranje postojećeg koda za DEADLINE raspoređivač i preimenovanje duplikata s novim imenom.

    Isječak koda 4.1: /kernel/sched/core.c:2179 – :2191 Primjer dupliciranja naredbi RB_CLEAR_NODE(&p->dl.rb_node);

    RB_CLEAR_NODE(&p->dl2.rb_node);

    init_dl_task_timer(&p->dl);

    init_dl2_task_timer(&p->dl2);

    init_dl_inactive_task_timer(&p->dl);

    init_dl2_inactive_task_timer(&p->dl2);

    __dl_clear_params(p);

    4.3.1. kernel/sched/fair.c Potrebno je napraviti izmjene u funkcijama others_have_blocked(), update_blocked_averages() i scale_rt_capacity().

    4.3.2. kernel/sched/deadline.c S obzirom na to da je određeno da je DEADLINE2 raspoređivač nižeg prioriteta od DEADLINE raspoređivača, potrebno je modificirati dl_sched_class kako bi se postavio taj prioritet. 2396 const struct sched_class dl_sched_class = {

    2397 .next = &dl2_sched_class,

    ...

    4.3.3. kernel/sched/deadline2.c Uz sva preimenovanja struktura, varijabli i funkcija, potrebno je postaviti i koji raspoređivač će biti sljedeći nižeg prioriteta modificiranjem dl2_sched_class. Sljedeći raspoređivač nižeg prioriteta postavljen je na rt_sched_class.

    Isječak koda TODO: kernel/sched/deadline2.c Postavljanje raspoređivača nižeg prioriteta 2395 const struct sched_class dl2_sched_class = {

    2396 .next = &rt_sched_class,

    2397 .enqueue_task = enqueue_task_dl2,

    2398 .dequeue_task = dequeue_task_dl2,

    2399 .yield_task = yield_task_dl2,

    2400

    ...

    2424 }

    4.3.4. uapi/linux/sched.h Potrebno je definirati novu zastavicu za SCHED_DEADLINE2, kako bi se deadline2 mogao postaviti kao raspoređivač za novi posao.

    Isječak koda TODO: uapi/linux/sched.h Definiranje nove zastavice za deadline2 raspoređivač 36 #define SCHED_NORMAL 0

  • 19

    37 #define SCHED_FIFO 1

    38 #define SCHED_RR 2

    39 #define SCHED_BATCH 3

    40 /* SCHED_ISO: reserved but not implemented yet */

    41 #define SCHED_IDLE 5

    42 #define SCHED_DEADLINE 6

    43 #define SCHED_DEADLINE2 7

    4.3.5. kernel/sched/Makefile Kako bi se uspješno povezale iskompajlirane datoteke prilikom kreiranja modificirane jezgre potrebno je u Makefile dodati i datoteku deadline2.o 19 obj-y += core.o loadavg.o clock.o cputime.o

    20 obj-y += idle.o fair.o rt.o deadline.o deadline2.o

    21 obj-y += wait.o wait_bit.o swait.o completion.o

    4.3.6. Ostale datoteke U navedenim datotekama potrebno je samo na par mjesta dodati duplicirani deadline kod:

    • kernel/time/posix-cpu-timers.c • kernel/time/hrtimer.c • kernel/sched/topology.c • kernel/sched/rt.c • kernel/sched/pelt.h • kernel/sched/pelt.c • kernel/sched/debug.c • kernel/sched/core.c

    4.3.7. Napomena U datotekama u kojima se duplicira kod za deadline2 i koje sadrže #include

    potrebno je dodati i #include

    U datoteka kernel/sched/core.c treba pažljivije dodavati deadline2 kod, s obzirom na to da je većina promjena u samoj logici, kako ne bi došlo do promjene u logici koda.

    4.4. Instalacija modificirane jezgre

    Nakon što se završi s modificiranjem jezgre potrebno je pokrenuti izgradnju (engl. build) jezgre. make -j `getconf _NPROCESSORS_ONLN` deb-pkg LOCALVERSION=-deadline2

    -j definira broj stvorenih poslova. Poželjno je stvoriti onoliko poslova koliko je procesora u računalu, s obzirom na to da postupak izgradnje jezgre traje nekoliko sati. Naredba get conf _NPROCESSORS_ONLN dohvaća trenutni broj aktivnih procesora. LOCALVERSION=-deadline2 služi kako bi se označili modificirani paketi za lakše razlikovanje modificiranog kernela s drugima. Nakon što je izgradnja jezgre gotova potrebno ju je instalirati. Izgrađeni paketi se nalaze jedan direktorij iznad trenutnog, a mogu se instalirati koristeći dpkg naredbu.s

  • 20

    cd ..

    sudo dpkg -i *deadline2*.deb

    Zadnji korak je restartati operacijski sustav, nakon čega će modificirana verzija biti instalirana. Trenutno instalirana jezgra dobije se pokretanjem naredbe: uname -r

  • 21

    5. ZAKLJUČAK

    U ovom radu napravljeno je istraživanje raspoređivanje poslova u Linux operacijskom sustavu. Proučavanje je rađeno na razini koda, gdje su manje bitni dijelovi izostavljeni, te pomoću provođenja postupaka modificiranja jezgre Linuxa, dodavanjem novog raspoređivača. Provedeni proces dodavanja kopije DEADLINE raspoređivača pruža pogled u povezanost samog sustava s implementacijama raspoređivača. Naglasak istraživanja dan je na radu samog raspoređivanja poslova u Linuxu i na CFS raspoređivaču poslova. Ovaj rad je napravljen kao uvod za daljnju modifikaciju raspoređivača poslova.

  • 22

    LITERATURA

    1. Bootlin, Linux kernel v5.0.0 izvorni kod, https://elixir.bootlin.com/linux/v5.0/source/kernel/sched/deadline.c, 20. 6. 2019.

    2. Leo Budin, Marin Golub, Domagoj Jakobović, Leonardo Jelenković, Operacijski sustavi, Element, 2010.

    3. Paul Menage, Cgroups, https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt, 25.6.2019.

    4. Dokumentacija sa kernel.org, Deadling Task Scheduling, https://www.kernel.org/doc/Documentation/scheduler/sched-deadline.txt, 25.6.2019

    5. Nick Congleton, How to Build a Custom Kernel on Ubuntu, https://www.maketecheasier.com/build-custom-kernel-ubuntu/, 24.6.2019.

    6. CFS scheduler, https://www.kernel.org/doc/Documentation/scheduler/sched-design-CFS.txt, 25.6.2019., 2015.

    7. Nikita Ishkov, A complete guide to Linux process scheduling, https://trepo.tuni.fi/bitstream/handle/10024/96864/GRADU-1428493916.pdf?sequence=1&isAllowed=y, 25.06.2019.

    https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txthttps://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txthttps://www.kernel.org/doc/Documentation/scheduler/sched-deadline.txthttps://www.maketecheasier.com/build-custom-kernel-ubuntu/https://www.kernel.org/doc/Documentation/scheduler/sched-design-CFS.txthttps://www.kernel.org/doc/Documentation/scheduler/sched-design-CFS.txthttps://trepo.tuni.fi/bitstream/handle/10024/96864/GRADU-1428493916.pdf?sequence=1&isAllowed=yhttps://trepo.tuni.fi/bitstream/handle/10024/96864/GRADU-1428493916.pdf?sequence=1&isAllowed=y

  • 23

    SAŽETAK

    Raspoređivanje poslova u Linuxu Ovaj rad istražuje sustav raspoređivanja poslova u Linuxu. Za bolje razumijevanje povezanosti sustava raspoređivanja poslova s raspoređivačima poslova, u jezgru Linuxa se dodaje kopija postojećeg raspoređivača poslova. Rad se može primijeniti kao uvod prije početka modifikacije raspoređivača poslova. Ključne riječi: diplomski rad, raspoređivanje poslova u Linuxu, promjena Linux jezgre

    SUMMARY

    Title: Task Scheduling in Linux Summary This thesis researches task scheduling in Linux. A copy of the existing scheduler is added to the Linux kernel, to get the better understanding of the interconnections between task scheduling and scheduler implementation. The thesis can be used as an introduction before implementing modifications to the schedulers. Keywords: master thesis, task scheduling in Linux, modifying Linux kernel