Virtuálna pamäť

Virtuálna pamäť je označenie pre schému správy pamäte v multitaskových operačných systémoch. Lineárny adresný priestor sa mapuje podľa potreby do fyzickej pamäte. Rieši zvyčajne problém obmedzenia veľkosti fyzickej pamäte (v systémoch so stránkovaním a swapovaním).
Efektívne použitie virtuálnej pamäte je závislé na podpore procesora. MMU (jednotka pre správu pamäte) vykonáva samotný preklad logickej (virtuálnej) adresy na fyzickú. Pre procesy je proces mapovania transparentný, operačný systém im ponúka model lineárnej pamäte.
Úvod.
Virtuálna pamäť alebo adresovanie virtuálnej pamäti je technika riadenia pamäti, používaná bežne viacúlohovými (multitasking) operačnými systémami, kde rôzne druhy nesusediacej pamäte sú prezentované aplikácii ako súvislá pamäť. Táto pamäť je označovaná ako virtuálny adresný priestor.
Virtuálna pamäť je technika dovoľujúca vykonanie procesov, ktoré sa nenachádzajú v operačnej pamäti celé. Výhodou tejto techniky je, že poskytuje používateľovi veľký pamäťový priestor pri využití malého množstva fyzickej pamäte. Zjednodušuje prácu programátora, pretože nie je potrebné vytvárať segmenty pre prekrytie a plánovať ich poradie zavedenia do pamäte. Tieto úlohy preberá správa pamäte.
Virtuálna adresná pamäť je typicky implementovaná v stránkovej pamäti systému (paged memory) často v kombinácii s pamäťovým swapovaním (anonymous memory paging). Pamäťové stránky uložené do primárneho pamäťového priestoru sú prepisované do sekundárneho pamäťového priestoru (stránkovací súbor, swapovací súbor, swapovacia partícia), čím systém uvoľňuje primárny pamäťový priestor pre načítanie ďalších procesov. Virtuálna pamäť dovoľuje aplikácii využívať väčší pamäťový adresný priestor, ktorý nie je pevne viazaný na fyzickej pamäti.
Pozadie.
Väčšina počítačov obsahuje štyri základné druhy pamäte: registre v procesore a cache pamäť procesoru (priamo spojené s procesorom), operačnú pamäť (umožňujúcu procesoru zapisovať a čítať pomerne rýchlo) a diskový odkladací priestor (zápis a čítanie je rádovo pomalšie, ale priestor je väčší). 
Použitie registrov procesora je zvyčajne ovládané kompilátorom. Rozhodnutie kedy bude použitá cache pamäť a kedy hlavná operačná pamäť je ovládané zväčša hardvérom počítača, pretože obidva druhy pamäte sú považované za fyzickú pamäť.
Veľa aplikácií však požaduje prístup k informáciám (kód alebo dáta), ktoré nemôžu byť uložené vo fyzickej pamäti. Toto je častý jav pri operačných systémoch, ktoré dovoľujú súčasný viacnásobný beh procesov (multitasking). Existuje viacero spôsobov, ako zabezpečiť riešenie tohto problému:
Virtuálna pamäť robí prácu programátorov oveľa jednoduchšou. Nezáleží na tom, koľko pamäte aplikácia potrebuje, bude sa správať ako keby mala prístup k hlavnej pamäti požadovanej veľkosti a jej dáta budú uložené do virtuálneho pamäťového priestoru. Programátor môže kompletne ignorovať potrebu správy presunu dát medzi rôznymi druhmi pamäte. Ak však programátor chce zabrániť častému swapovaniu, mal by venovať pozornosť minimalizáciu počtu blokov, ku ktorým sa pristupuje často.
Virtuálna pamäť býva zvyčajne implementovaná dvoma spôsobmi:
Stránkovanie na žiadosť.
Virtuálna pamäť je zvyčajne implementovaná použitím stránok. Procesy sú umiestnené na disku. Keď chceme vykonávať proces, presunieme ho do pamäte, nemusíme ho však do pamäte presúvať celý, ale len jeho časť. Za tento proces je zodpovedný tzv. stránkovač – pager. Stránkovač predpokladá, ktoré stránky budú pre beh procesu potrebné a presunie ich do pamäti, čím sa zníži réžia potrebná na výmenu procesov v pamäti. 
Ku správnej implementácii virtuálnej pamäte je potrebné zabezpečiť mapovanie (prepojenie) virtuálnej pamäte k fyzickej pamäti, a to tak, aby bolo možné rozpoznať, ktoré dáta patria do fyzickej pamäte, aby ich bolo možné rozlíšiť a swapovať. Operačný systém ukladá adresnú prekladaciu tabuľku, mapovanú z virtuálnych čísiel stránok na fyzickú, v dátovej štruktúre známej ako stránková tabuľka. Vo väčšine počítačov, sú tieto prekladacie tabuľky uložené vo fyzickej pamäti.
V stránke najnižšie poradie bitov virtuálnej adresy je zachované a užívané priamo ako najnižšie poradie bitov aktuálnej fyzickej adresy. Najvyššie poradie bitov je považované za kľúče jednej alebo viacerých adries prekladacej tabuľky, ktoré poskytujú vysoké poradie bitov aktuálnej fyzickej adresy. Pre tento dôvod rozsah za sebou idúcich adries vo virtuálnom adresnom priestore, bude prekladaný v odpovedajúcom rozsahu súvisiacich fyzických adries. Pamäť zodpovedajúca takémuto rozsahu je nazývaná stránka. Veľkosť stránky je obyčajne v rozsahu 512 B až 8192 B (v súčasnosti je často používaná veľkosť 4kB), aj keď na špeciálne účely môžu byť použité aj 4MB alebo i väčšie stránky.
Pre rozlíšenie, ktoré stránky sa nachádzajú v pamäti sa používa systém validačného bitu. Keď je nastavený do stavu platná, znamená to, že stránka je uložená v pamäti. V opačnom prípade je stránka buď neplatná (nepatrí do adresného priestoru procesu) alebo nie je v pamäti. Položka v tabuľke stránok pre stránku, ktorá je v pamäti je nastavená ako obyčajne, ale položka stránky, ktorá nie je v pamäti, je označená ako neplatná, alebo obsahuje adresu stránky na disku.
Ak sa proces nikdy neobráti na stránku, ktorá je označená ako neplatná, teda potrebuje len tie stránky, ktoré sú skutočne obsiahnuté v pamäti, prebehne tak, ako keby bol celý obsiahnutý v pamäti.
Ak sa proces obráti na stránku, ktorá nie je v pamäti a je označená ako neplatná, spôsobí výpadok stránky – page fault. Prerušenie spôsobí presunutie požadovanej stránky do pamäte v nasledovných krokoch:
Takýmto spôsobom je možné odštartovať i proces, ktorý nemá v pamäti žiadnu stránku. Vtedy ide o čisté stránkovanie na žiadosť, stránka sa nikdy nepresúva do pamäte, pokiaľ nie je požadovaná.
Hardvérové prostriedky, ktoré sú potrebné pre realizáciu stránkovania na žiadosť sú:
Pri zvýšenom počte procesov, ktoré sú naraz spustené môže nastať situácia, keď niektorý z procesov požaduje zavedenie stránky z odkladacieho priestoru do pamäte, ale v pamäti nie je žiadny voľný rámec. Táto situácia sa zvyčajne rieši metódou nahradzovania stránok. Myšlienkou je, že v prípade, že v pamäti nie je voľný žiadny rámec, nájdeme rámec, ktorý sa momentálne nevyužíva, jeho obsah zapíšeme do odkladacieho priestoru a nahradíme ho načítanou stránkou. Týmto sa však zvyšuje počet prenosov stránok, čo znižuje efektivitu činnosti celého systému. Zlepšenie prináša využitie tzv. bitu modifikácie, ktorý sa nastavuje ak sa na stránku v pamäti zapisuje. V prípade, že nahradzujeme stránku, ktorá nemá nastavený bit modifikácie, nie je potrebné ju zapisovať na disk, čím sa ušetrí jeden diskový prenos. Je však potrebné riešiť problémy výberu algoritmov pre prideľovanie voľných rámcov a nahradzovanie stránok.
Dôležitým problémom je voľba algoritmu, ktorým sa bude vyberať stránka, ktorá sa má nahradiť. Existuje viacero algoritmov, ktoré je možné použiť: 
Algoritmus FIFO prideľuje každej stránke čas jej príchodu do pamäte (FIFO fronta v pamäti, nie je potrebný presný čas). Pre nahradenie sa vyberá stránka, ktorá je najdlhšie v pamäti. Algoritmus je jednoduchý, no nie veľmi dobrý, pretože rovnako ako môže nahradiť stránku, ktorá sa dlho nepoužíva, môže nahradiť aj často používanú stránku, čo spôsobí čoskoro ďalší výpadok stránky.
Optimálny algoritmus je algoritmus, ktorý nahradzuje stránku, ktorá nebude potrebná najdlhšiu dobu, čo zaručuje najmenší možný počet výpadkov stránok pri danom pevnom počte rámcov. Veľmi ťažko sa však realizuje, pretože vyžaduje znalosť budúcich odkazov na stránky.
Algoritmus LRU je aproximáciou optimálneho algoritmu, kde blízku budúcnosť nahradzujeme nedávnou minulosťou. Ku každej stránke je pridelený čas jej posledného použitia. Keď sa nahradzuje stránka, vyberá sa taká, ktorá najdlhšie nebola používaná. Používajú sa dve implementácie tohto algoritmu: počítadlami alebo zásobníkom. 
Prideľovanie rámcov je taktika, ktorá určuje, koľko rámcov bude pridelených ktorému procesu. Obyčajne čím menej rámcov vlastní proces, tým viac výpadkov stránok vyvoláva, čo spomaľuje chod systému. Minimálny počet rámcov, ktoré majú byť pridelené procesu, vyplýva z maximálneho počtu rámcov, na ktoré sa je možné pri vyvolaní jednej inštrukcie odvolať. Ako algoritmy sa používajú algoritmus spravodlivého rozdelenia medzi procesy a algoritmus proporcionálneho prideľovania.
V prípade spravodlivého rozdeľovania rámcov medzi procesy sa počet pre m rámcov a n procesov určuje zaokrúhlením výrazu m/n. Toto rozdelenie neberie do úvahy veľkosť procesu, čo môže viesť ku plytvaniu pri malých procesoch a nedostatku pri veľkých procesoch.
Pri proporcionálnom prideľovaní každý proces dostáva rámce podľa svojej veľkosti. Ak celkový počet rámcov je m, požiadavky všetkých procesov S, požiadavky procesu i na pamäť sú si pridelíme ai rámcov procesu pi, kde ai je približne: ai = (si/S) . m.
Dôležitým faktorom je tiež rozhodnutie, či pri nahradzovaní stránky sa táto stránka vyberá lokálne alebo globálne, to znamená, či sa vyberá len spomedzi rámcov pridelených procesu alebo spomedzi všetkých rámcov v pamäti. Od toho aj závisí, či sa počet rámcov pridelených procesu môže dynamicky meniť.
Segmentácia na žiadosť.
V prípade chýbajúcej hardvérovej podpory umožňujúcej efektívny systém stránkovania na žiadosť, používa sa virtualizačná technika segmentácie na žiadosť. Program sa v tomto prípade zavádza do pamäte po segmentoch, ktoré sú predmetom výmeny. Pri odkaze na segment, ktorý nie je v pamäti, sa vygeneruje prerušenie pre výpadok segmentu. Správa pamäte nájde pre požadovaný segment vhodný úsek v pamäti a presunie ho tam. Využíva pritom striasanie. Segmentácia na žiadosť má silnejšie väzby na štruktúru programu a minimalizuje vnútornú fragmentáciu. Nevýhodou je nebezpečenstvo vonkajšej fragmentácie.
Je ale tiež možné, virtuálna stránka bola označená za nedostupnú z dôvodu, že stránka nebola pridelená. V takýchto prípadoch je stránka fyzickej pamäti alokovaná a naplnená nulami, tabuľka stránok je modifikovaná na jej popis, a program je reštartovaný ako v predošlom prípade.
Implementácia VM v OS Linux.
Virtuálna pamäť v operačných systémoch Linux je implementovaná prostredníctvom stránkovania. V prípade použitia 32 bitovej architektúry systému je možné adresovať 4GB fyzickej pamäte (232). V prípade, že procesor obsahuje implementáciu správy pamäte (MMU – Memory Management Unit), podporuje koncept virtuálnej pamäte. V tomto prípade sú linuxovým kernelom vytvárané tabuľky stránok (page tables), ktoré mapujú virtuálne adresy na fyzické adresy. Znamená to, že každý proces v systéme môže adresovať až 4GB pamäte, pričom z pohľadu procesu, je on sám jediným procesom bežiacim v systéme. 
Linuxový kernel rozdeľuje 4GB virtuálneho adresného priestoru procesu na dve časti – 3GB a 1GB. Nižšie 3GB virtuálneho adresného priestoru procesu sú prístupné ako užívateľský priestor (user-space), vyšší 1GB je rezervovaný pre virtuálne adresovanie kernelom a užívateľský proces tam zvyčajne nepristupuje. Virtuálna oblasť kernelu (3-4GB adresného priestoru) sú mapované na 1GB fyzickej pamäte. Zvyšné 3GB adresovateľnej fyzickej pamäte sú dostupné pre procesy.
Mapovanie virtuálnych adries na fyzické adresy sa vykonáva prostredníctvom linuxového kernelu. Pri vytvorení nového procesu (pomocou fork()), kernel vytvára novú sadu tabuliek stránok (page tables) pre vytvorený proces. Referenčné adresy pre proces sú virtuálnymi adresami. Nie sú nutne mapované na zhodné fyzické adresy v pamäti. Virtuálna adresa je odovzdaná správe pamäte (MMU), ktorá ju skonvertuje na fyzickú adresu založenú na tabuľkách vytvorených kernelom. Teda, dva rôzne procesy sa môžu odkazovať na rovnakú adresu (napr. 0x08329), ale v skutočnosti sa odkazujú na dve odlišné adresy v závislosti od tabuliek stránok.
Dôvod implementácie virtuálnej pamäte v operačných systémoch GNU/Linux nie je len ten, že väčšina aplikácii obsahuje kód a dáta, ktoré nie sú nikdy využívané všetky naraz a preto nie je nutné udržiavať celý proces vo fyzickej pamäti, dôvod je i v koncepte použitia zdieľaných knižníc pre rôzne rutiny, ktoré sú často využívané. Bolo by zbytočné, aby si každý program vytváral svoje vlastné kópie týchto knižníc, preto môže byť jedna kópia využívaná súčasne viacerými bežiacimi procesmi. Kód a dáta z týchto knižníc sú preto namapované do virtuálneho adresného priestoru každého procesu využívajúceho danú knižnicu.
Je nepravdepodobné, aby proces využíval naraz všetok kód a dáta, ktoré sú uložené v pamäti. Pamäť môže obsahovať kód a dáta, ktoré sa využívajú iba v špecifických situáciách. Linux využíva techniku stránkovania na žiadosť pre implementáciu virtuálnej pamäte. Stránka virtuálnej pamäte je presúvaná do fyzickej pamäte len vtedy, keď ju proces požaduje. Pre rozlíšenie, ktoré stránky sa nachádzajú v pamäti sa používa systém validačného bitu. Keď je nastavený do stavu platná, znamená to, že stránka je uložená v pamäti.Ak proces požaduje kód alebo dáta, ktoré nie sú obsiahnuté vo fyzickej pamäti, systémový hardware generuje výnimku chyby stránky a odovzdá kontrolu kernelu, aby problém vyriešil. 
Linuxový kernel potrebuje spravovať všetky oblasti virtuálnej pamäte. Obsah virtuálnej pamäte každého procesu je opísaný štruktúrou typu mm_struct, na ktorú proces odkazuje v dátovej štruktúre task_struct. Dátová štruktúra mm_struct obsahuje informácie potrebné na vyriešenie výnimky chyby stránky. Obsahuje ukazovatele do tabuľky stránok procesu – do zoznamu štruktúr typu vm_area_struct, z ktorých každá reprezentuje oblasť virtuálnej pamäte patriacej procesu. Keďže jednotlivé oblasti virtuálnej pamäte pochádzajú z rôznych zdrojov, Linux zabezpečuje abstraktnosť prístupu do virtuálnej pamäte pomocou rutín správy pamäte.
Dátová štruktúra vm_area procesu je pristupovaná opakovane kernelom vždy v prípade, keď dôjde k vyvolaniu výnimky chyby stránky, vytvárajú sa nové stránky vo virtuálnej pamäti alebo sa modifikujú informácie v existujúcich stránkach. Z tohto dôvodu je časť nájdenia správneho záznamu v štruktúre vm_area kritický pre výkonnosť systému. Preto pre urýchlenie prístupu Linux udržiava záznamy vm_area v dátovej štruktúre AVL stromu, keď ľavý smerník odkazuje na prvok z nižšou začiatočnou štartovacou adresou a pravý smerník na prvok z vyššou štartovacou adresou virtuálnej pamäte. Za urýchlenie prístupu sa v tomto prípade platí zvýšeným obslužným časom pri vložení nového záznamu do štruktúry AVL stromu.
V prípade, že počet voľných rámcov vo fyzickej pamäti dochádza, pamäťový manažment Linuxu musí zabezpečiť uvoľnenie stránok vo fyzickej pamäti. Tieto funkcie sú zabezpečované pomocu démona Kernel Swap Daemon (kswapd). Kernel Swap Daemon je zodpovedný za efektívne fungovanie pamäťového manažmentu. Démon je spúšťaný počas Init procesu a následne je aktivovaný v periodických intervaloch po uplynutí časovača. V prípade, že démon zistí nedostatok volných rámcov v pamäti, zabezpečí ich uvoľnenie aplikáciou nasledovných postupov:
Démon vyberie vhodný proces, ktorého stránky budú swapované. Swapovanie sa však netýka všetkých stránok procesu, vyberá sa len určitý predvolený počet stránok a v prípade potreby sa proces uvoľňovania stránok opakuje pri ďalšej aktivácii démona. Algoritmus, ktorý je používaný pre výber stránky, ktorá bude presunutá do swap priestoru vychádza zo systému nazývaného page ageing. Každá stránka má počítadlo (udržiavané v štruktúre mem_map_t), ktoré je informáciou pre systém, či je daná stránka vhodným kandidátom na swapovanie. Keď je stránka v pamäti alokovaná, jej počítadlo je nastavené na hodnotu 3. Vždy, keď je zaznamenaný prístup na stránku, jej počítadlo je znova zvýšené o hodnotu 3, až do maximálnej hodnoty 20. Pri každom spustení Kernel Swap Daemon znižuje hodnotu počítadla stránky o 1. Tieto nastavenia môžu byť zmenené v konfigurácii systému. 
Démon taktiež nemôže swapovať ľubovolnú stránku len z ohľadom na intenzitu jej používania. Niektoré stránky majú nastavený tzv. dirty bit, čo zamedzuje ich výberu pre swapovanie. Swapovanie nie je možné stránky, ktoré sú uzamknuté v pamäti, alebo zdielané. Pre zdieľané stránky je používaný oddelený komplexný algoritmus swapovania.