OS2/Projekat 2022
Projekat 2022. godine je prvi projekat iz Operativnih sistema 1 i 2 u kom se koristi xv6 operativni sistem na RISC-V arhitekturi. U ovom vodiču se nalaze korisni saveti pri izradi projekta.
Dodavanje interfejsa raspoređivača
Interfejs definisan postavkom za raspoređivač je isti onaj iz školskog jezgra:
struct proc *get(); // Дохватање спремног процеса из реда чекања
void put(struct proc *); // Убацивање спремног процеса у ред чекања
xv6 u sebi sadrži Round-robin raspoređivač direktno implementiran u funkciji scheduler(). Neophodno je zameniti ovaj algoritam sa traženim interfejsom. Mesta od značaja su ona gde proces menja stanje.
get()uscheduler()nakon uključivanja prekida - prelaz iz RUNNABLE u RUNNING.put()uyield()- kad proces predaje kontekst nekom drugom procesu.put()uuserinit()- kad se kreira prvi korisnički proces.put()ufork()- kad se forkuje nov proces.put()uwakeup()- prelaz iz SLEEPING u RUNNABLE.put()ukill()- kad proces treba da se završi treba da ga probudimo.
Implementiranje preotimanja po vremenskom kvantumu
Koncept vremenskog kvantuma (timeslice) iz ovog projekta je isti kao onaj iz školskog jezgra na OS1. xv6 menja kontekst (preotima) procese na svaki tajmerski prekid. Ovo se može lako promeniti da podržava preotimanje nakon isteka kvantuma ili nepostojanje preotimanja (nonpreemptive scheduling). Mesta od značaja:
- Poziv
yield()uusertrap()se treba dogoditi samo ako je istekao kvantum, ili nikad ako nema preotimanja. Ovde bi se oduzimala trenutna vrednost sve dok kvantum ne istekne. - Isto i za
kerneltrap(), koji je samo slučaj tajmerskog prekida u kernel režimu. - Praćenje vremenskog kvantuma nekog procesa se može implementirati na razne načine, ali najčešći je pamtiti ga u
struct proc, gde bi onda trebalo postavljati njegovu vrednost uuserinit()ifork().
Dodavanje novog sistemskog poziva
- Definišete potpis sistemskog poziva sa korisničke strane u
user.h - Dodati njegov naziv iz prethodnog fajla u Perl skriptu
usys.plza generisanje koda za poziv (ne menjatiusys.Sjer je to automatski generisan assembly fajl - briše se pri svakom prevođenju). - Definisati broj sistemskog poziva (22 je sledeći u nizu) u
syscall.h - Implementirati sistemski poziv u fajlu
sysproc.c. Potpis mora bitiuint64 sys_poziv(void)- Dohvatanje celobrojnih argumenata, pokazivača i stringova je omogućeno uz pomoćne funkcije
argint(),argaddr()iargstr()respektivno u fajlusyscall.c. - Prvi argument pomoćnih funkcija je indeks argumenta u potpisu funkcije sa korisničke strane, a sama vrednost se prosleđuje preko pokazivača koji je drugi argument.
- Povratna vrednost 0 iz pomoćnih funkcija označava uspeh.
argraw(int n)direktno vraća vrednosti registaraa0-a5koji se nominalno koriste za prenos argumenata pri pozivu procedure.
- Dohvatanje celobrojnih argumenata, pokazivača i stringova je omogućeno uz pomoćne funkcije
- Dodati naziv funkcije iz prošle tačke u niz pokazivača funkcije
syscallsusyscall.c. Indeks funkcije u nizu mora da se slaže iz indeksa usyscall.h.
Okruženje
Makefile
Debagovanje korisničkih programa
Da bi debagovali korisničke programe, morate u konfiguraciji za debagovanje u okruženju promeniti binarni fajl koji će gdb-multiarch da debaguje (podrazumevano sam kernel).
- Meni Run → Edit Configurations → Remote Debug → Debug (ili vaš naziv konfiguracije) → Symbol file promenite na binarni fajl korisničkog programa (nalaze se u direktorijumu
/user/i svi počinju sa donjom crtom). - Postavite breakpoint, pokrenite OS sa
qemu-gdbi u njemu pokrenite izabrani program.
Promena učestanosti tajmerskog prekida
U svrhu testiranja na odbrani je ponekad traženo da se poveća učestanost prekida radi preciznijih merenja performansi (pomoću sistemskog poziva uptime()) i vidljivijeg efekta raspoređivanja. Interval tajmera se može promeniti u fajlu start.c u funkciji timerinit().
Tumačenje scause i sepc
Preskočene su rezervisane vrednosti.
| scause vrednost | Značenje | Potencijalni problem |
|---|---|---|
| 0 | Adresa u PC nije poravnata | Kernel je promenio kontekst u nevalidan proces (verovatno je raspoređivač vratio nevalidan proces). |
| 1 | Greška u pristupu instrukciji | |
| 2 | Ilegalna instrukcija | Ukoliko koristite floating-point tipove, oni nisu podržani na ovoj implementaciji RISC-V. |
| 3 | Breakpoint | Ne bi trebalo da se pojavi kao razlog za paniku. |
| 4 | Adresa sa koje se čita nije poravnata | Loš pokazivač. |
| 5 | Greška u pristupu pri čitanju | |
| 6 |
| |
| 7 | Greška u pristupu pri pisanju/atomičnoj instrukciji. | |
| 8 | ecall iz korisničkog režima | Ne bi trebalo da se pojavi kao razlog za paniku. |
| 9 | ecall iz supervizorskog (kernel) režima | Ne bi trebalo da se dešava uopšte u xv6. |
| c | Stranična greška pri učitavanju instrukcije | Kernel je promenio kontekst u nevalidan proces (verovatno je raspoređivač vratio nevalidan proces). |
| d | Stranična greška pri čitanju |
|
| f | Stranična greška pri pisanju/atomičnoj instrukciji |
|
Vrednost sepc registra označava vrednost PC u trenutku kad je nastala greška. Može se tačno pronaći mesto u kodu pretraživnjem ove adrese u fajlu kernel.asm koji sadrži i C kod kernela i generisani RISC-V asembli sa tačnom adresom instrukcija.