[OSy] Zadani 5. tematu semestralni ulohy
Martin Decky
decky at d3s.mff.cuni.cz
Mon Jan 4 00:11:48 CET 2016
Vazeni kolegove,
v priloze tohoto emailu naleznete rozsirene zadani 5. semestralni ulohy
z predmetu Operacni systemy. Prosim, venujte tomuto zadani pozornost i v
tom pripade, ze mate v planu prijit na nejblizsi cviceni a resit
prezencni ulohu -- zadani 5. prezencni ulohy se bude take tykat tematu
systemovych volani a bude vyzadovat znalost latky z prednasky (pripadne
z doporucene literatury, ktera je uvedena na konci rozsireneho zadani).
Specialne upozornuji, ze kod Kalista byl na mnohych mistech netrivialne
upraven, aby mohl podporovat (byt velmi rudimentalne) spousteni
uzivatelskych procesu. Neni mozna od veci, pokud si v nejakem vhodnem
nastroji porovnate rozdily mezi zdrojovym stromem verze 0.9.5 a 0.9.6.
Pokud se rozhodnete implementovat rozsirene zadani 5. semestralni ulohy,
tak sva reseni muzete odevzdavat az do 18. 1. 2016 (vcetne). Odevzdani
provadejte opet tak, ze svou modifikaci Kalista (tj. vse, co je potreba
ke spusteni, otestovani a ohodnoceni Vaseho reseni) zabalite do archivu
(ZIP, TAR.BZ2 apod.) a poslete jako prilohu na emailovou adresu
nswi004 at d3s.mff.cuni.cz
Opet DURAZNE APELUJEME, abyste vypracovani reseni nenechavali na
posledni chvili a meli tak pripadne realnou moznost reagovat na nasi
zpetnou vazbu k Vasemu reseni, Podrobneji viz zadani 1. ulohy [1].
V pripade libovolnych dotazu k zadani nebo k formalnim zalezitostem
nevahejte vyuzit tento mailing list.
[1] https://d3s.mff.cuni.cz/pipermail/osy/2015-October/002164.html
S pozdravem
Martin Decky
-------------- next part --------------
========================================================================
Semestralni uloha z predmetu
Operacni systemy
Tema 5.: Systemova volani
Rozsirene zadani
========================================================================
Datum zverejneni zadani: 4. 1. 2016
Datum odevzdani reseni: 18. 1. 2016
------------------------------------------------------------------------
Cilem 5. tematu semestralni ulohy je rozsirit jadro Kalisto o podporu
behu uzivatelskych procesu. To zahrnuje predevsim infrastrukturu pro
vytvareni a beh uzivatelskych procesu a pro systemova volani, ktera
zpristupnuji relevantni funkce jadra uzivatelskym procesum. Zadani ma
formu rozhrani, ktere je nutno naimplementovat, a je doplneno sadou
jednotkovych testu, jimiz musi implementace uspesne projit.
Pri vypracovani vychazejte z vyukoveho jadra Kalisto ve verzi 0.9.6,
do ktereho doplnte chybejici funkcionalitu. Kalisto ve verzi 0.9.6 je
k dispozici ke stazeni z URL:
http://d3s.mff.cuni.cz/osy/download/kalisto-0.9.6.tar.bz2
Pokud zadani nespecifikuje nejaky detail, je zavazne chovani, ktere
ocekavaji testy. Pokud testy dane chovani netestuji, zadani si podle
uvazeni dodefinujte a sve rozhodnuti zdokumentujte pomoci vhodnych
komentaru ve zdrojovem kodu reseni.
Rozhrani systemovych volani --------------------------------------------
Mechanismus systemovych volani umoznuje volat na strane uzivatelskeho
prostoru sluzby jadra a predavat jim argumenty a na strane jadra psat
obsluzne rutiny techto sluzeb.
Pri implementaci tohoto mechanismu je obvykle kladen duraz na rozumnou
efektivitu a rozumnou budouci rozsiritelnost o nove sluzby a jejich
obsluzne rutiny. Za timto ucelem se pouzivaji ruzne programatorske
abstrakce, ktere umoznuji snadno integrovat nove typy systemovych
volani a jejich argumenty. Verejne uzivatelske funkce tedy nejsou
primo systemovymi volanimi, ale pouze v ramci sve implementace
pouzivaji jedno nebo vice systemovych volani. Podobne na strane jadra
neni obsluha systemovych volani "zadratovana" primo do tela obsluzne
rutiny vyjimky, ale pouziva se neprima vazba pomoci vhodne datove
struktury (tabulky systemovych volani).
Jde o chybu navrhu, pokud se systemova volani pouzivaji na takove
sluzby a funkce, ktere mohou byt implementovany snadno primo
v uzivatelskem prostoru. Pripadne chyby v jadernem kodu mohou totiz
mit mnohem horsi nasledky nez chyby v uzivatelskem kodu a proto neni
vhodne chapat jadro jako "sdilenou knihovnu", na kterou by mely
uzivatelske procesy delegovat sve bezne funkce.
Kvuli ochrane jadra pred chybami v uzitelskem kodu je take dulezite
dusledne testovani spravnosti a konzistence argumentu systemovych
volani predavanych z uzivatelskeho prostoru. Predevsim je nutne
overovat, ze ukazatele na datove struktury ukazuji na korektne
namapovanou pamet v ramci adresoveho prostoru volajiciho procesu (tj.
pri manipulaci s touto pameti v jadre nemuze dojit k vyjimce,
nemuze dojit k pristupu k pameti jineho procesu a nemuze dojit
k nedovolenemu pristupu k pameti jadra). Je nutne kontrolovat
i konzistenci vsech ostatnich argumentu a jejich chybne hodnoty
indikovat chybovym navratovym kodem systemoveho volani, pripadne
ukoncenim chybujiciho procesu.
Cilem techto ochran je, aby chyba uzivatelskych procesu nemohla
ohrozit stabilitu jadra a operacniho systemu jako takoveho.
Obecne pozadavky -------------------------------------------------------
Nasledujici doporuceni odrazi pozadavky na uroven zdrojovych textu,
ktere budou hodnoceny pri odevzdani reseni ulohy.
- Vyhybejte se pouzivani numerickych konstant primo v kodu, nahradte
je makry.
- Pouzivejte prazdne radky a blokove komentare k oddeleni logickych
casti kodu.
- Pouzivejte vhodnym zpusobem mezery pro zprehledneni a usnadneni
porozumeni kodu. Snazte se, aby styl vaseho kodu pokud mozno
odpovidal stylu jiz existujiciho kodu.
- Vyhybejte se psani prilis dlouhych funkci nebo funkci s prilis
velkou urovni vnorenych bloku.
- Vyhybejte se vytvareni zdrojovych souboru, ktere obsahuji
nesouvisejici funkce, pripadne umistovani zdrojovych souboru do
nevhodnych adresaru.
- Pouzivejte makra ci inline funkce k nahrade slozitych podminkovych
vyrazu.
- Pouzivejte jednotny jazyk pro komentare.
- Pouzivejte jednotny jazyk pro identifikatory funkci a promennych
a pro nazvy souboru.
- Pouzivejte systematicke identifikatory funkci a promennych.
Zadani ulohy -----------------------------------------------------------
Po uspesne inicializaci jadra Kalisto 0.9.6 dojde ke spusteni jedineho
uzivatelskeho procesu, jehoz binarni obraz je nahran spolecne
s kernelem a dalsimi potrebnymi daty primo do pameti simulatoru. Tento
uzivatelsky proces vyuziva uzivatelskou behovou infrastrukturu
staticky linkovane knihovny librt.a.
Start uzivatelskeho procesu vypada tak, ze jadro zacne provadet kod
procesu od adresy, kde se nachazi vstupni bod behoveho prostredi
knihovny librt.a, ktery provede nezbytnou inicializaci a zavola funkci
main() uzivatelskeho procesu. Po navratu z funkce main() pak behove
prostredi proces ukonci.
V ramci knihovny librt.a naimplementujte nebo doplnte implementaci
nasledujicich funkci. Uvedomte si, u kterych funkci je vhodne, aby
jejich primarni logika byla implementovana pomoci systemoveho volani
(napr. putc()), a u kterych funkci to naopak vhodne neni (napr.
printf(), gets(), malloc(), free()). V pripade nekterych funkci (napr.
puts()) neni tato volba jednoznacna -- existuji argumenty pro jednu
i pro druhou moznost.
V pripade, ze systemova volani predavaji jadru ukazatele na
uzivatelskou pamet, tak je nutne overovat, ze tyto ukazatele miri na
korektne namapovanou pamet v ramci adresoveho prostoru volajiciho
procesu (tj. pri manipulaci s touto pameti v jadre nedojde k vyjimce,
nedojde k pristupu k pameti jineho procesu a nedojde k nedovolenemu
pristupu k pameti jadra). Je nutne kontrolovat i konzistenci vsech
ostatnich argumentu a jejich chybne hodnoty indikovat chybovym
navratovym kodem systemoveho volani, pripadne ukoncenim chybujiciho
procesu.
* size_t putc(const char chr)
Funkce vypise znak na konzoli. Vraci pocet vypsanych znaku.
* size_t puts(const char *str)
Funkce vypise retezec na konzoli. Vraci pocet vypsanych znaku.
* size_t printf(const char *format, ...)
Funkce vypise formatovany retezec na konzoli, stejne jako v knihovne
libc. Formatovaci kody by mely podporovat znaky (%c), retezce (%s),
cela cisla v desitkove (%d, %u, %i) a v sestnactkove (%x) soustave,
ukazatele (%p). Neni nutne implementovat modifikatory pro
zarovnavani a platne cislice. Funkce vraci pocet vypsanych znaku.
* char getc(void)
Funkce precte a vrati znak z klavesnice. Pokud neni ve vyrovnavaci
pameti klavesnice zadny znak, zablokuje volajici vlakno a ceka na
stisk klavesy. Cekani na znak by melo byt pasivni, aktivni polling
je velmi nevhodne reseni.
* ssize_t gets(char *str, const size_t len)
Funkce precte nejvice @len - 1 znaku z klavesnice do bufferu @str.
Cteni je ukonceno pri precteni (a ulozeni) znaku '\n' nebo pri
dosazeni limitu. Prectene znaky jsou vzdy ukonceny znakem 0. Vraci
EINVAL, pokud @len == 0, jinak pocet znaku ulozenych do bufferu bez
ukoncovaci 0. Cekani na jednotlive znaky by opet melo byt reseno
pasivne.
* void exit(int retval)
Funkce ukonci provadeni hlavniho vlakna aktualniho procesu, tedy
efektivne ukonci cely proces. Pri ukoncovani nesmi dojit
k deadlocku. Veskere prostredky procesu jsou uvolneny. Pokud
v jadre jiz nebezi zadny uzivatelsky proces, ukonci se beh celeho
jadra.
* makro assert(EXPR)
Pokud neni definovano makro NDEBUG, makro assert() vyhodnoti vyraz
EXPR a pokud je vysledek nulovy, vypise informaci o nazvu funkce,
souboru a cisle radku, na kterem nebyl splnen predpoklad EXPR,
a zavola exit(). Pokud je makro NDEBUG definovano, neudela makro
assert() nic.
* makro dprintf(ARGS...)
Pokud neni definovano makro NDEBUG, makro dprintf() vypise na
konzoli informaci o nazvu funkce a cislo radku, na kterem bylo
pouzito, a formatovany retezec ARGS. Pokud je makro NDEBUG
definovano, neudela makro dprintf() nic.
Nasledujici funkce umoznuji uzivatelskemu procesu dynamicky alokovat
a uvolnovat pamet. Spravce uzivatelske pameti typicky pracuje s jednou
oblasti virtualni pameti, jejiz velikost je dana aktualnimi pametovymi
naroky procesu (alokator uzivatelske pameti dynamicky zada jadro
o jeji zvetseni ci zmenseni).
Vzhledem k omezenym moznostem jadra Kalisto muzete alokator
uzivatelske pameti implementovat za pomoci oblasti virtualni pameti
fixni velikosti, o ktere budete zadat jadro.
Implementace samotneho algoritmu alokatoru uzivatelske pameti muze byt
velmi jednoducha, muzete napr. prevzit a upravit puvodni alokator
kernelove haldy z Kalista. Je vsak nutne, aby alokator haldy
v uzivatelskem procesu a alokator kernelove haldy byly na sobe
nezavisle.
* void *malloc(const size_t size)
Funkce alokuje blok pameti pozadovane velikosti. Vraci NULL, pokud
nebylo mozne blok alokovat, jinak ukazatel na zacatek alokovaneho
bloku.
* void free(const void *ptr)
Funkce uvolni blok pameti, na ktery ukazuje @ptr a ktery byl predtim
naalokovan funkci malloc().
Jednotkove testy -------------------------------------------------------
K overeni spravne funkcnosti implementace slouzi testy ulozene
v podstrome user/tests/basic zdrojoveho stromu Kalista 0.9.6.
Infrastruktura pro spousteni a vyhodnoceni techto jednotkovych testu
je implementovana pomoci skriptu tests-user.sh. Pro splneni zadani je
potreba, aby reseni uspesne proslo vsemi dodanymi jednotkovymi testy,
pricemz neni dovoleno modifikovat logiku testu.
K integraci s jednotkovymi testy pridejte do hlavickoveho souboru
librt.h vhodne #include direktivy, ktere zajisti vlozeni hlavickovych
souboru s potrebnymi deklaracemi.
Doporucena literatura --------------------------------------------------
[1] Studijni text k predmetu Operacni systemy, kapitola Process
Management, http://d3s.mff.cuni.cz/~ceres/sch/osy/text/ch02.html
[2] Wikipedia: User space,
https://en.wikipedia.org/wiki/User_space
More information about the NSWI004
mailing list