Virtuaalmälu
Sissejuhatus
Arvuti käivitab programme, käivitades instruktsioome RAMis. Ta käivitub instruktsiooni ühel aadressil ja siis liigub järgmise aadressini. Ta suudab samuti hüpata ühelt aadressilt üle teisele (ehk siis loops). Vanadel 8-bitistel arvutitel või tänapäevastes mikrokontrollerites kasutatakse kogu RAMi otse ja seal puudub igasugune peemptive multitasking mis lubab käivitada mitmel programmil korraga. Iga aadress on unikaalne ja viitab kindlale füüsikalisele aadressile.
Virtuaalmälu lubab igal protsessil omada omaenda aadressiruumi ja need pole unikaalsed. Näiteks aadress 4095 täendavad erinevatele programmidele hoopis erinevat instruktsiooni. Muidugi peavad ka need aadressid olema kusagil füüsikalises RAMis mistõttu virtuaalmälu mapib virtuaalaadressid füüsikalisteks
Aga kuidas see töötab? Kujutame ette kahte programmi ja kumbki neist kasutab 5MB RAMi. Programm üks asub füüsikalises mälus aadresisl 5242880 ja läheb 5MB-ni välja. Programm kaks algab 10485760 ja teeb sama. Kui esimene protsess tahab kasutada aadressi 0 ühendab arvuti aadressi 0 aadressile 5242880. Kui ta tahab kasutada aadressi 1 siis 5242881 jne.
See maping või ühendamine tehakse ära otse rauas spetsiaalse komponendi poolt nimega memory management unit MMU.
Boonusteks selle süsteemi puhul on kolm asja:
- Rakendusele pole oluline kus ta füüsilises ramis asub
- Rakendus pääseb liigi vaid oma aadressiruumile ja ei saa teisi tarkvarasid segada
- App ei pea asetsema ramis järjestiku ning katkematuna. Ehk selle võib jagada mitmeteks tükkideks, mis puistatud mööda rami laiali.
Näiteks saame jagada 2 programmi mällu hoopis järgnevalt:
Hoolimata sellest, et esimene programm on jaotatud kahte blokki, on MMUs talle tehtud maping järjestikune ja katkematu. Seda, kuidas MMU virtuaalseid aadresse füüsikalisteks mapib haldab operatsioonisüsteemi kernel.
Programmi enda seisukohalt vaadataes annab virtuaalmälu igale protsessile tunde, et ta on ainuke programm kogu süsteemis.
Page tabelid
Selleks, et neid ühendusi teha vajab MMU tabelit, kus igal real on virtuaalne aadress (VA) ja füüsiline aadress (PA)
Probleem sellise üks-ühele mapigu tabeliga on näiteks selles, et kui programm vajab 300MB mahtu siis tuleb MMU tabelisse kanda 79 miljonit rida.
Selliste olukordade vältimiseks ja MMU tabeli väikseks hoidmiseks jagatakse mälu lehtedeks (pages). Kindlaksmääratud suurusega blokkideks, mis igale programmile kasutada antud. Tüüpiline lehe suurus on 4K ehk 4096 baiti. See tähendab, et 300MB vajab nüüd vaid 76 800 kirjet. Iga kirje sisaldab 4 baiti seega on tabel 300KB suurune ja märksa hallatavam. Iga page on laaditud mäluasukohta nimega page frames.
Swapping
Demand paging teeb võimalikuks, et vaid osa programmi on korraga mällu laetud. Selle saavutamiseks kasutatakse swappingut.
Lisaks VMi ja PMi vahelisele mapingule sisaldab page tabel selleks veel sellist infot nagu validbit.
Kui validbit on ok siis on info põhimälus. Kui mitte siis on andmed kõvakettal ja nende poole pöördumisel kutsutakse välja page fault, kuna andmed on puudu ja need tuleb lugeda kõvakettalt. Programm ootab, kuni andmed on kätte saadud. Niikaua kuni programm ootab, võtab operatsioonisüsteem korraks töö üle, et andmed kohale kirjutada. Seda nimetatakse context switchiks.
Et süsteem saaks kasutada rohkem operatiivmälu, kui arvutil tegelikult füüsiliselt olemas on, tuleb aeg-ajalt teha saalimisoperatsioone virtuaalmälu ja päris mälu vahel. Operatsioonisüsteem peab pidevalt järge selle üle, millised leheküljed on parasjagu kasutuses ja milliseid enam ei kasutata või millised pole mingi pikema ajavahemiku vältel enam üldse kasutuses olnud. Kui ilmneb, et on tarvis mõnda uut lehekülge kasutada, ent füüsilisele mälule viitavad lehekülgede tabelid on juba täis, asendatakse ebatarvilikud leheküljed füüsilises mälus lehekülgede tabeli abil ära ning leheküljed, mida enam ei kasutata, suunatakse varuks virtuaalmällu.
Mälukasutuse uurimine linux süsteemis
Üks lihtsamaid ja esmaseid töövahendeid vaatamaks, kuidas mälu on jagatud on ps käsk
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND www-data 1465 0.0 0.1 531636 9128 ? S 15:15 0:00 /usr/sbin/apache2 -k start www-data 9090 0.0 0.1 531636 9128 ? S 15:59 0:00 /usr/sbin/apache2 -k start www-data 26201 0.0 0.1 531636 9128 ? S 14:36 0:00 /usr/sbin/apache2 -k start www-data 26335 0.0 0.1 531636 9128 ? S 14:38 0:00 /usr/sbin/apache2 -k start www-data 27315 0.0 0.1 531636 9128 ? S 14:40 0:00 /usr/sbin/apache2 -k start
RSS tähendab the Resident Set Size ja see näitab palju mälu on protsessi poolt allocated ja hetkel RAMis. Tegemist pole kuigi täpse numbriga, kuna ei sisalda mälu mis on jagatud teekide all ja mälu mis on väljasaalitud.
VSZ tähendab Virtual Memory Size ja see kujutab endast kogu mälu, mida protsess saab kasutada. Kaasaarvatud mälu mis on väljasaaltiud või on jagatud teekide all.
Järgmine täpsem töövahend on pmap.
# pmap -x 16747 16747: -bash Address Kbytes RSS Dirty Mode Mapping 0000000000400000 976 12 0 r-x-- bash 00000000006f3000 4 4 4 r---- bash 00000000006f4000 36 36 36 rw--- bash 00000000006fd000 356 356 356 rw--- [ anon ] 00007fc8c72c9000 44 12 0 r-x-- libnss_files-2.23.so 00007fc8c72d4000 2044 0 0 ----- libnss_files-2.23.so 00007fc8c74d3000 4 4 4 r---- libnss_files-2.23.so 00007fc8c74d4000 4 4 4 rw--- libnss_files-2.23.so 00007fc8c74d5000 24 0 0 rw--- [ anon ] 00007fc8c74db000 44 12 0 r-x-- libnss_nis-2.23.so 00007fc8c74e6000 2044 0 0 ----- libnss_nis-2.23.so 00007fc8c76e5000 4 4 4 r---- libnss_nis-2.23.so 00007fc8c76e6000 4 4 4 rw--- libnss_nis-2.23.so 00007fc8c76e7000 88 20 0 r-x-- libnsl-2.23.so 00007fc8c76fd000 2044 0 0 ----- libnsl-2.23.so 00007fc8c78fc000 4 4 4 r---- libnsl-2.23.so 00007fc8c78fd000 4 4 4 rw--- libnsl-2.23.so 00007fc8c78fe000 8 0 0 rw--- [ anon ] 00007fc8c7900000 32 20 0 r-x-- libnss_compat-2.23.so 00007fc8c7908000 2044 0 0 ----- libnss_compat-2.23.so 00007fc8c7b07000 4 4 4 r---- libnss_compat-2.23.so 00007fc8c7b08000 4 4 4 rw--- libnss_compat-2.23.so 00007fc8c7b09000 1792 544 0 r-x-- libc-2.23.so 00007fc8c7cc9000 2048 0 0 ----- libc-2.23.so 00007fc8c7ec9000 16 16 16 r---- libc-2.23.so 00007fc8c7ecd000 8 8 8 rw--- libc-2.23.so 00007fc8c7ecf000 16 12 12 rw--- [ anon ] 00007fc8c7ed3000 12 8 0 r-x-- libdl-2.23.so 00007fc8c7ed6000 2044 0 0 ----- libdl-2.23.so 00007fc8c80d5000 4 4 4 r---- libdl-2.23.so 00007fc8c80d6000 4 4 4 rw--- libdl-2.23.so 00007fc8c80d7000 148 56 0 r-x-- libtinfo.so.5.9 00007fc8c80fc000 2044 0 0 ----- libtinfo.so.5.9 00007fc8c82fb000 16 16 16 r---- libtinfo.so.5.9 00007fc8c82ff000 4 4 4 rw--- libtinfo.so.5.9 00007fc8c8300000 152 132 0 r-x-- ld-2.23.so 00007fc8c8516000 16 16 16 rw--- [ anon ] 00007fc8c8525000 4 4 4 r---- ld-2.23.so 00007fc8c8526000 4 4 4 rw--- ld-2.23.so 00007fc8c8527000 4 4 4 rw--- [ anon ] 00007ffe12e67000 84 16 16 rw--- [ stack ] 00007ffe12fdd000 8 4 0 r-x-- [ anon ] ffffffffff600000 4 0 0 r-x-- [ anon ] ---------------- ------- ------- ------- total kB 18252 1356 536
Lingid
https://et.wikipedia.org/wiki/Virtuaalm%C3%A4lu
https://www.androidauthority.com/what-is-virtual-memory-gary-explains-747960/