Puteți găsi aici assignment-ul pentru tema: Classroom assignment
Pentru întrebări legate de temă, vă rugăm să deschideți un issue la UPB-CS-Rust/teme cu titlul: [scheduler] <title issue>. (titlul issue-ului e ce scrieți voi).
- Utilizarea limbajului Rust
- Utilizarea
trait-urilor
- Tema trebuie sa conțină un fișier numit README.md care să conțină explicații referitoare la modul de rezolvare al temei. (-0.1p)
- Tema trebuie implementată în Rust, utilizând doar funcții din biblioteca standard de Rust. Orice altă implementare va conduce la anularea temei. (0p)
- Puteți folosi orice structuri de date doriți pentru reprezentarea proceselor și a cozilor, irelevant dacă sunt sau nu eficiente
Tema trebuie rezolvată individual. Orice tentativă de copiat duce la acordarea punctajului 0p pentru teme. Utilizăm un sistem automat de detectare a copiatului. Dacă avem dubii legate de implementarea voastră, vă vom adresa întrebări suplimentare în legătură cu tema.
NU PUBLICAȚI COD SURSĂ. Această acțiune se încadrează la copiat, lucru care va conduce la primirea punctajului 0p pentru tema.
Scopul acestei teme este de a crea un planificator de procese. Acesta trebuie să pună la dispoziție trei algoritmi de planificare:
- Round Robin
- Round Robin cu priorități
- Completely Fair Schedule (CFS)
Planificatorul face parte din sistemul de operare. Deoarece scrierea codului în sistemul de operare este dificilă, în spațiul utilizatorului a fost implementat un simulator de procese.
Scopul acestei teme este să implementați un planificator de procese. Acesta va simula un planificator de procese preemptive, într-un sistem uniprocesor, care utilizează algoritmii Round Robin, Round Robin cu priorități și CFS (Completely Fair Schedule).
Pentru fiecare planificator, trebuie să implementați trait-ul Scheduler. Aceasta presupune implementarea tuturor celor trei funcții:
next- următorul proces de executatstop- primiți informații despre motivul pentru care procesul s-a opritlist- returnează starea proceselor
Pentru aceasta, puteți crea fișiere separate pentru fiecare planificator și le puteți exporta în scheduler/src/schedulers/mod.rs.
Trebuie să implementați doar
trait-ulSchedulerpentru cei 3 algoritmi de planificare. Alte informații prezentate mai jos sunt detalii de implementare ale modelului existent, astfel încât să înțelegeți mai bine cum funcționează planificatorul.
Într-un sistem real, pentru controlul execuției, contorizarea timpului de execuție al unui proces se realizează la fiecare întrerupere de ceas.
Pentru ușurința implementării, șablonul de temă va simula un sistem real ca acesta:
- Sistemul simulat va folosi timpul virtual (logic) independent de timpul real pentru a număra timpul de operare pe procesor.
- Veți considera că o instrucțiune durează o singură perioadă de ceas (unitate logică de timp).
- Fiecare dintre funcțiile prezentate mai sus reprezintă o singură instrucțiune executabilă de către un proces la un moment dat.
Această bibliotecă oferă trait-urile și structurile necesare pentru implementarea unui planificator de procese.
Această enumerare conține stările posibile ale unui proces pentru simularea noastră:
Ready- Procesul așteaptă să fie planificatRunning- Procesul este planificatWaiting- Așteaptă după un eveniment sau o operație I/O
Această enumerare conține acțiunea pe care procesul o cere de la sistemul de operare. De asemenea, reprezintă valoarea întoarsă de funcția Scheduler::next, pe care trebuie să o implementați:
Run {pid, timeslice}- Rulați procesul cu PID-ulpidpentru un număr maxim detimesliceunități de timpSleep (time_units)- Suspendați procesul de la planificare (trecere în stareaWaiting) pentru cel puțintime_unitsunități de timpDeadlock- Sistemul de operare nu mai poate continua, deoarece toate procesele așteaptă evenimente. În acest caz, niciun alt proces nu poate trimite evenimente, ceea ce înseamnă că toate procesele vor aștepta la nesfârșit.Panic- Procesul cu PID-ul 1 s-a oprit.Done- Nu mai sunt procese de planificat.
Această enumerare conține motivul pentru care un proces s-a încheiat și sistemul de operare a rulat planificatorul:
Syscall {syscall, remaining}- Procesul a trimis un apel de sistemSyscall;remainingreprezintă numărul de unități de timp pe care procesul nu le-a folosit.Expired- intervalul de timp alocat procesului a expirat și procesul a fost preemptat
Această enumerare conține apelurile de sistem pe care procesele le fac către planificator:
Fork(process_priority)- Creează un nou proces și returnează PID-ul acestuia.Sleep(amount_of_time)- Cereți planificatorului să suspende procesul pentru o anumită perioadă de timpWait(event_number)- Procesul va aștepta în stareaProcessState::Waitingpână când un alt proces emite un apel de sistemSyscall::Signalcu acest număr de eveniment.Signal(event_number)- Toate procesele care așteaptă acest eveniment vor fi trezite și plasate în stareaProcessState::Ready.Exit- Cereți planificatorului să încheie procesul. Procesul nu va mai fi planificat niciodată și va fi eliminat din lista de procese pe care planificatorul le urmărește.
Această enumerare conține rezultatul întors de către un apel de sistem:
Pid(pid)- PID-ul noului proces, este întors doar după un apel de sistemSyscall::Fork.Succes- Apelul de sistem s-a executat cu succes.NoRunningProcess- Apelul de sistem a fost emis când nu a fost planificat niciun proces.
Această bibliotecă este folosită pentru a simula execuția proceselor de către un procesor.
Conține următoarele informații despre un proces:
PidStateTimings:- durata totală de execuție (de la fork până la exit)
- timpul de execuție al apelului de sistem
- timpul de rulare
Simulatorul folosește următoarele funcții:
fork- Trimite un apel de sistemSyscall::Forkexec- Execută o unitate de timp.wait- Trimite un apel de sistemSyscall::Waitsignal- Trimite un apel de sistemSyscall::Signalsleep- Trimite un apel de sistemSyscall::Sleepexit- Oprește procesul; procesul informează sistemul de operare că a terminat de executat
Primul apel de sistem primit de către planificator trebuie să fie un
fork, pentru a crea primul proces, altfel se va emite o eroare.
Pentru acest algoritm, toate procesele au aceeași prioritate și sunt planificate unul după altul. După ce un proces a fost planificat, acesta va fi plasat la sfârșitul cozii.
Procesele noi vor fi plasate la sfârșitul cozii.
Va ține o coadă cu procese în așteptare (sleep). Vor fi la coadă în ordinea în care au intrat în starea sleep. Înainte de fiecare planificare, puteți extrage procese din coadă care pot rula și le puteți adăuga la sfârșitul cozii de planificare (ready).
Procesul care tocmai a fost executat va fi adăugat ultimul în coadă.
Acest algoritm este identic cu cel anterior, cu următoarea modificare: prioritatea inițială a procesului este cea pe care o primește la fork. Această prioritate nu poate fi niciodată depășită. De fiecare dată când un proces își depășește timpul alocat, adică nu se opreste singur (prin utilizarea un apel de sistem înainte de a fi preemptat), este penalizat cu 1. De fiecare dată când procesul renunță la procesor înainte de a-și depăși timpul alocat, este recompensat cu 1.
Prioritatea nu poate fi mai mică de 0 și nici mai mare de 5.
Pentru planificare, sunt luate în considerare numai procesele cu cea mai mare prioritate. Dacă niciunul dintre ele nu poate fi planificat (este în starea waiting), se vor lua în considerare procesele cu prioritate mai mică. Dacă niciunul nu poate fi planificat nici aici, se vor lua în considerare procesele cu prioritatea și mai mică, etc.
Pentru compararea prioritățiilor dintre processe, se va implementa
trait-ulPartialOrd.
Acest algoritm este folosit de Linux. Puteți găsi mai multe detalii la CFS: Perfectly Fair Process Scheduling in Linux. Varianta implementată aici va ține cont de următoarele aspecte:
- timpul virtual
- durata de timp variază în funcție de numărul de procese, timpul real este timpul inițial împărțit la numărul de procese, timpul de referință nu poate fi mai mic de 1.
După fiecare execuție a unui proces vom adăuga numărul de unități de procesare executate de proces la
virtualruntime(valoarea este de faptquantum_time - process.quantum).
Pentru compararea
virtualruntime-ului dintre processe, se va implementatrait-ulPartialOrd. Pentru adăugarea devirtualruntimese va implementatrait-ulAdd.
