7. cvičenie – COW fork ?

Copy-on-Write Fork pre xv6

Vašou úlohou je implementovať copy-on-write fork pre jadro xv6. Korektnosť implementácie môžete overiť programami cowtest a usertests.

Pred začiatkom práce prepnite repozitár do vetvy cow:

Problém

Systémové volanie fork() v xv6 kopíruje celý adresný priestor rodiča do priestoru potomka. Ak je adresný priestor rodiča veľký, kopírovanie môže trvať dlho (relatívne k rýchlosti procesora). Naviac sa týmto tiež zbytočne plytvá pamäťou — niektoré stránky nemodifikuje ani rodič, ani potomok. To znamená, že by mohli byť spoločné pre oba procesy. Najlepším príkladom neefektívnosti takéhoto kopírovania je volanie exec() hneď po forku. exec() uvoľní všetky ťažko nakopírované stránky, bez toho, aby nejakú použil. Treba však mať neustále na pamäti, že až vtedy, ak by rodič či dieťa chceli zapísať do spoločnej stránky, až potom je potrebné urobiť kópiu údajov, ktoré sa v nej nachádzajú.

Riešenie

Cieľom copy-on-write (COW) forku je odložiť alokáciu a kopírovanie fyzickej pamäte pre detský proces až kým kópie nie sú skutočne potrebné (t.j. buď rodič a/alebo dieťa sa pokúsi o zápis do spoločnej stránky).

COW fork() vytvorí iba tabuľku stránok pre detský proces. Záznamy v tabuľke (PTE) budú ukazovať na fyzické stránky (údaje v RAM) rodičovského procesu. Zároveň záznamy v tabuľke stránok oboch procesov budú označené ako nezapisovateľné. Ak sa jeden z procesov pokúsi zapísať niečo do COW stránky, CPU vynúti výpadok stránky. Obsluha výpadkov stránky v jadre systém tento výpadok zachytí, alokuje stránku fyzickej pamäte pre proces, ktorý spôsobil výpadok, skopíruje obsah pôvodnej (spoločnej) stránky do novej stránky a upraví súvisiace záznamy v tabuľke stránok, aby ukazovali na novú stránku so zapisovateľným príznakom PTE_W. Po návrate z obsluhy výpadku bude môcť takto užívateľský proces pokračovať v zápise do vlastnej kópie stránky.

Uvoľňovanie fyzických stránok procesov bude pri COW forku o niečo zložitejšie. Jedna fyzická stránka môže byť namapovaná vo viacerých procesoch. Uvoľnená by mala byť až po zániku poslednej referencie, teda keď ju odmapuje posledný proces, ktorý ju používa.

Program cowtest

Na otestovanie vašej implementácie môžete použiť program cowtest (jeho zdroják nájdete v user/cowtest.c). cowtest obsahuje niekoľko testov, na neupravenom kóde xv6 zlyhá hneď prvý test. Takto to vyzerá:

Test simple alokuje viac ako polovicu dostupnej fyzickej pamäte a potom zavolá fork(). Fork zlyhá, pretože nie je miesto na skopírovanie celého adresného priestoru rodiča.

Implementácia je korektná, ak úspešne prebehnú programy cowtest a usertests. Takto by to malo vyzerať:

Pomôcky

Na cvičení s lenivým alokátorom ste sa oboznámili s časťami xv6, ktoré sú relevantné pre implementáciu copy-on-write. Toto cvičenie by ste ale nemali zakladať na kóde lenivého alokátora, preto nezabudnite pred začiatkom práce zmeniť vetvu repozitára (viď hore úvod cvičenia).

Ako postupovať

Modifikujte uvmcopy()tak, aby namapovala fyzické stránky rodiča do dieťaťa namiesto alokácie nových stránok. Aj v rodičovi, aj v dieťati vynulujte príznak PTE_W. Modifikujte usertrap()tak, aby rozoznala výpadky stránok. Ak nastane výpadok stránky na COW stránke, alokujte novú stránku pomocou kalloc(), skopírujte obsah starej stránky do novej stránky a namapujte novú stránku do adresného priestoru procesu, ktorý výpadok spôsobil s nastaveným príznakom PTE_W. Ďalej zabezpečte, aby každá fyzická stránka bola uvoľnená až vtedy, keď je uvoľnená posledná PTE referencia (ale nie predtým, to by bolo pre procesy využívajúce danú stránku trochu posmutnejšie!). Pozrite sa do kalloc.c a pouvažujte, či by sa tam nehodilo implementovať počítanie referencií. Na záver upravte copyout()tak, aby používal vyššie popísanú schému pri výpadku stránky COW.

Tiež sa vám môže hodiť záznam pre každú PTE, ktorý hovorí o tom, či je stránka namapovaná COW. Môžete na to použiť vyhradené bity RSW (reserved for software, viď. RISC-V špecifikácia).

usertests testuje viac scenárov ako cowtest, takže nezabudnite skontrolovať, či všetky testy naozaj prešli.

Niekoľko užitočných makier a definícií pre príznaky tabuliek stránok nájdete na konci súboru kernel/riscv.h.

Počítanie času

Aby ste mali v hodnotiacom skripte plný počet bodov, musíte v koreňovom priečinku zdrojákov xv6 vytvoriť textový súbor time.txt, ktorý bude obsahovať jedno celé číslo — počet hodín, ktoré ste strávili riešením tohoto cvičenia.

Keďže sa k tomuto súboru nedopracujeme, môžete sa nám pochváliť mailom, koľko času ste na cvičení strávili.

Nezabudnite spustiť make grade na overenie, či je vaša implementácia korektná.

Týmto je cvičenie hotové. Svoje zmeny môžete commitnúť do svojho repozitára.