ITF225129 Innføring i operativsystemerObligatorisk oppgave 9: Page replacementI denne obligatoriske oppgaven skal du programmere tre algoritmer for å gjøre page replacement i minnehåndtering. Programmene som du lager skal ta utgangspunkt i kode som er gitt i oppgaven. For mer bakgrunnstoff om minnehåndtering, se læreboken og læringsmodulen i Canvas. Oppgaveteksten består av to deler:
1 Virtuelt minne og algoritmer for page replacementDatamaskinene våre kjører mange prosesser som har behov for mye minne. Spesielt multimedia-applikasjoner kan kreve flere GB med RAM. Noen av disse prosessene er i seg selv for store til å passe inn i det tilgjengelige minnet. Det samlede minnebehovet til alle prosesser på systemet kan ofte være (mye) større enn det fysiske minnet som er tilgjengelig i user space. Vi trenger derfor å kunne kjøre programmer som bare har deler av minnet sitt liggende i RAM. Løsninger der hver prosess får ett stort, sammenhengende fysisk minneområde, vil ikke fungere i praksis. Med mange minnekrevende prosesser blir det etter hvert umulig å finne ledige "hull" i minnet som er store nok. Det tar også alt for lang tid å lese/skrive store minneområder til/fra disk når minnet er fullt. Det er derfor utviklet løsninger som deler opp minnet for en prosess i mindre deler, slik at noen deler kan ligge i RAM og andre midlertidig på disk:
I denne oppgaven skal vi se nærmere på virtuelt minne og paging. 1.1 Virtuelt minneFor å løse problemet med for lite fysisk minne, bruker vi en abstraksjon som kalles for "virtuelt minne" ("virtual memory"). Kompilatoren som oversetter f.eks. C-koden vår til eksekverbare maskininstruksjoner, adresserer dette "ikke-eksisterende" virtuelle minnet for å lese/skrive data. Det samlede virtuelle minnet er oftest større enn det fysiske minnet som er tilgjengelig i maskinen. Når en prosess kjører, forholder den seg bare til det virtuelle minnet. Denne løsningen kan litt forenklet beskrives slik:
1.2 PagingVirtuelt minne brukes alltid sammen med en teknikk som kalles for "paging". Dette løser problemene forbundet med store og sammenhengende minneområder. Paging tillater at en prosess har deler av eget minne i RAM, mens andre deler kan være lagret på disk. Det blir også mer effektivt å gjøre "swapping", dvs. å flytte minne mellom RAM og disk, når vi bruker paging. 1.2.1 Pages i det virtuelle minnetDet virtuelle minneområdet for en prosess deles inn i mindre deler som kalles for "pages". En page er en sammenhengende blokk med virtuelt minne. Vi kan tenke på en page som et sammenhengende område i prosessens "array" med virtuelt minne. Den starter i en gitt indeks og har en lengde som er antall bytes i pagen. Typisk pagestørrelse i et Linux-system er 4kB. Det virtuelle minnet til prosessen deles opp i pages som nummereres fra page 0 (første page) og videre utover i "minnearrayen". En virtuell minneadresse vil (hvis vi forenkler litt) bestå av to deler:
Figuren nedenfor viser (forenklet) et eksempel på sammenhengen mellom en virtuell minneadresse og det virtuelle minnet:
1.2.2 Fysiske page frames og pagetabellerDet fysiske primærminnet deles opp i tilsvarende page frames. En page frame er et område av RAM som har samme størrelse som en virtuell page. Hver virtuell page som en prosess bruker vil være lagret i en fysisk page frame. Operativsystemet og CPU'ens minnestyring (med MMU) sørger for at en prosess som adresserer en virtuell page får lest fra/skrevet til riktig page frame. En page frame kan ligge lagret i RAM, eller den kan være "swappet ut" og ligge lagret på disk. Det betyr at hele eller deler av minnet som en prosess bruker kan ligge utenfor RAM. Det samlede minnebehovet til alle prosessene kan derfor være vesentlig større enn hva det faktisk er plass til i maskinens RAM. Koblingen mellom virtuelt og fysisk minne for en prosess gjøres med bruk av en pagetabell, som håndteres av den delen av operativsystemet som kalles Memory Manager. Hvert element i en pagetabell, et page table entry, lagrer informasjon for én virtuell page med prosessminne. Den viktigste informasjonen i et slikt entry er den fysiske adressen til en page frame, der dataene i den virtuelle pagen er lagret fysisk. Vi kan tenke på pagetabell som en funksjon som avbilder virtuelle minneadresser over på fysiske minneadresser. Figuren nedenfor gir et (svært forenklet) bilde av virkemåten til en pagetabell:
I denne figuren brukes den samme virtuelle minneadressen [23,132] som ble vist i figuren i avsnitt 1.2.1. I pagetabellens indeks 23, som er nummeret på den virtuelle pagen, finner vi verdien 9. Dette er nummeret til en page frame i det fysiske minnet, der dataene i virtuell page 23 faktisk ligger lagret. Den riktige minnecellen i RAM adresseres da ved å legge til offset (132) til page frame adressen. Virtuell og fysisk minnecelle som svarer til hverandre er skravert på figuren. 1.3 Page fault og page replacementFordi det samlede virtuelle minnet kan være større enn kapasiteten til RAM, vil innholdet i en page frame enten ligge i RAM eller være swappet ut på disk. Dette håndteres av Memory Manager i OS, som lagrer og vedlikeholder diskadressene til page frames som ikke er i RAM. Hvis en prosess adresserer en virtuell page som ikke ligger i RAM, får vi et avbrudd som kalles for en page fault. Memory Manager må da sørge for at den riktige page frame leses fra disk og inn i RAM, før prosessen kan fortsette:
Men:
1.4 Page replacement algoritmerFordi diskaksesser er svært tidkrevende i forhold til å lese/skrive i RAM, ønsker vi så få page faults som mulig. Hvis vi bare velger en tilfeldig page for replacement (lagring på disk), vil vi ofte velge mye brukte pages. Disse vil da raskt måtte leses inn igjen, og vi får mye diskbruk og dårlig effektivitet. Gode page replacement algoritmer prøver å finne lite brukte pages. For å få til dette bruker de bl.a. informasjon som lagres i entries i pagetabellen. Figuren nedenfor viser noe av innholdet som typisk lagres for hver virtuell page i prosessens pagetabell:
Vi ser at en slik entry bl.a inneholder:
I tillegg inneholder et page table entry to statusbits som typisk brukes av page replacement algoritmer:
Nedenfor er det beskrevet tre relativt enkle algoritmer for page replacement som du skal programmere. En av dem bruker statusbit til å velge hvilken page som skal tas ut av RAM. Det kan også brukes ytterligere informasjon for å gjøre page replacement. Det er vanlig å lagre tidspunktet når en page ble lagt inn i RAM. I aging-algoritmen som er beskrevet i pensum, lagres det en "R-bit historikk" for å se hvilke pages som er minst brukt "i det siste". Algoritmen LRU (se nedenfor) bruker en liste med tidspunktene for siste lesing/skriving av hver page. I beskrivelsen av de tre algoritmene nedenfor, og i programmene som du skal skrive, skal vi bruke denne informasjonen om pages:
I tabellen ovenfor er det følgende data, med tidspunkter angitt i "systemtid", for fire pages som vi kan anta ligger i RAM:
Spørsmålet som besvares nedenfor for de ulike algoritmene er: Hvilken page vil her bli valgt ut for replacement? 1.4.1 First-In-First-OutAlgoritmen First-In-First-Out (FIFO) er svært enkel: Ved page replacement velges den page som har ligget lengst i RAM. FIFO bruker bare dataene om "ankomst-tid" til RAM. For eksempelet i tabellen ovenfor vil algoritmen måtte gå gjennom kolonnen "Load", der vi finner tidspunktet for når pagen ble lagt inn i RAM. Den vil da velge page nummer 3 som den page som skal flyttes til disk:
I en standard implementering av FIFO-algoritmen ville man brukt en vanlig kø til å lagre pages, for å få den effektiv uten søk etter minste verdi for "Load". Nye pages vil da legges bakerst i kø, og replacement gjøres ved å ta ut første page i køen. Du skal ikke programmere noen kø i din besvarelse, men bare finne minste verdi for "Load" ved å gå gjennom en array med page-strukturer (se nedenfor). Merk at FIFO-algoritmen ikke tar hensyn til hvor ofte en page leses/skrives. Den er derfor lite effektiv og brukes ikke i praksis, men er i stedet utgangspunkt for andre og bedre algoritmer for page replacement. 1.4.2 Least Recently UsedAlgoritmen Least Recently Used (LRU) er basert på følgende idé: Pages som er mye brukt nylig vil antagelig også bli brukt på nytt om kort tid. LRU-algoritmen tar ut den page i RAM som er minst brukt i den "siste tiden" før page fault skjedde. Effektiviteten til LRU avhenger av hvor langt man "ser bakover", dvs. hvordan man definerer denne "siste tiden". Det kan bevises at LRU er tilnærmet optimal hvis vi tar vare på alle minneaksesser, vektet med tidspunkt, som gjøres for hver page. Men dette blir for langsomt i praksis, fordi det krever at vi vedlikeholder en sortert liste av alle pages hver gang minnet leses/skrives. En enkel variant av LRU får vi ved alltid å ta vare på tidspunktet for siste gang en page ble referert til (tiden da den sist ble lest eller skrevet av prosessen). Dette er gjort i tabellen med fire pages som er vist avsnitt 1.4 ovenfor, i kolonnen "Last":
Her vil en enkel LRU-algoritme bare gå gjennom tidene for siste referanse. I dette tilfellet velges page 1 ut for replacement, siden den har minst verdi for "Last". 1.4.3 Second ChanceAlgoritmen Second Chance ligner på FIFO, men den sjekker også R-bit for å unngå å velge pages som nylig er brukt. Anta at det skjer en page fault ved (system)tiden T. Second Chance for page replacement kan beskrives slik:
Second Chance vil første sjekke "eldste" page, deretter nest eldste osv. Den fungerer mye bedre enn FIFO fordi den vil "kaste ut" pages som har ligget lenge i RAM uten å bli brukt. Algoritmen fungerer som FIFO hvis R=1 for alle pages. Vi skal se nøyere på Second Chance algoritmen når den kjøres på samme eksempel som ovenfor. Den vil bare trenge å bruke kolonnene for "load time" og referenced bit R:
I en standard implementering ville man også her, som for FIFO, brukt en vanlig kø til å lagre pages. Du skal ikke programmere noen kø i din besvarelse, men bare gå gjennom en array med page-strukturer (se nedenfor). 1.5 Simulering av page replacement algoritmerI oppgavene nedenfor skal du programmere tre C-funksjoner som simulerer/implementerer page replacement algoritmene beskrevet ovenfor. Hver funksjon skal bare skrive ut en linje med informasjon om hvilken page som algoritmen har valgt. 1.5.1 ForenklingerVi kan anta at det har oppstått en page fault i en prosess ved systemtiden T. Prosessminnet er fullt og det må gjøres page replacement. Det skal velges ut én page fra et lite antall pages i RAM. Valget skal gjøres med en page replacement algoritme. 1.5.2 InputInndataene til programmet er en fil der det ligger informasjon om N pages. Først på filen ligger antall pages N. Deretter kommer det én linje med fem data for hver page. Alle dataene er heltall, og er de samme som er brukt i eksemplet vi har sett ovenfor:
Datafilen for dette eksemplet vil se slik ut:
Det er gitt en funksjon read_file() i koden nedenfor som leser inn pagedataene fra fil. Du vil altså ikke trenge å programmere dette selv. 1.5.3 Datastruktur for page framesDataene for hver page frame skal lagres i en struct page_frame. En slik struktur skal inneholde de fem heltallsverdiene for pagen som leses inn fra fil. Alle de N pagene skal lagres i en array PF med page-frame-strukturer. Arrayen PF skal deklareres globalt i programmet, utenfor funksjonene og main(), slik at den er tilgjengelig i all koden. Det samme gjelder for antall pages, N, og systemtiden T. 1.5.4 C-kode som skal brukes i oppgaveneNedenfor er det gitt ufullstendig kode for et C-program som simulerer page replacement med tre ulike algoritmer. Du skal bruke denne koden som utgangspunkt for din egen besvarelse på oppgavene i del 2. Koden kan gjerne skrives om og formateres anderledes. Strukturen struct page_frame og arrayen PF med page frames er allerede lagt inn i koden, sammen med de globale variablene N og T. Systemtiden T er gitt en verdi som passer med testdataene som skal leses inn. Det er også gitt en funksjon read_file() som oppretter arrayen PF og leser alle page frames inn fra fil. Hovedprogrammet main() leser et filnavn fra bruker og kaller read_file() for å lese pagedataene. Deretter utføres det tre kall på funksjoner som simulerer page replacement med hver sin algoritme. Du skal programmere disse tre funksjonene. Se kommentarene i koden nedenfor for en nærmere forklaring av variabler og hva programmet skal utføre.
2 OppgaverDet er gitt tre (forhåpentligvis) enkle oppgaver som skal besvares med C-kode. For å teste programmene dine kan du bruke disse to datafilene som input:
Oppgave 1Programmer ferdig funksjonen first_in_first_out() i koden gitt ovenfor, slik at den implementerer FIFO-algoritmen for page replacement. Funksjonen skal gå gjennom de innleste pagedataene og skrive ut hvilken page som velges for replacement. For eksemplet med fire pages gitt i avsnitt 1.4 ovenfor (og på filen T0.txt), skal utskriften se slik ut:
Oppgave 2Programmer ferdig funksjonen least_recently_used() i koden gitt ovenfor, slik at den implementerer LRU-algoritmen for page replacement. Funksjonen skal gå gjennom de innleste pagedataene og skrive ut hvilken page som velges for replacement. For eksemplet med fire pages gitt i avsnitt 1.4 ovenfor (og på filen T0.txt), skal utskriften se slik ut:
Oppgave 3Programmer ferdig funksjonen second_chance() i koden gitt ovenfor, slik at den implementerer algoritmen Second Chance for page replacement. Funksjonen skal gå gjennom de innleste pagedataene og skrive ut hvilken page som velges for replacement. For eksemplet med fire pages gitt i avsnitt 1.4 ovenfor (og på filen T0.txt), skal utskriften se slik ut:
Hva skal du levere?Svarene på oppgave 1, 2 og 3 skal legges inn i en og samme fil med navn oblig_9.c. C-filen skal lastes opp i Canvas. |