I software funzionano sul sistema operativo su una premessa molto semplice: richiedono memoria. Il sistema operativo del dispositivo lo fornisce sotto forma di RAM. La quantità di memoria richiesta può variare: alcuni software richiedono una memoria enorme, altri richiedono una memoria irrisoria. La maggior parte (se non tutti) gli utenti eseguono più applicazioni contemporaneamente sul sistema operativo e, dato che la memoria è costosa (e la dimensione del dispositivo è limitata), la quantità di memoria disponibile è sempre limitata. Quindi, dato che tutti i software richiedono una certa quantità di RAM e tutti possono essere eseguiti contemporaneamente, il sistema operativo deve occuparsi di due cose:
- Che il software gira sempre fino a quando l'utente non lo interrompe, cioè non dovrebbe interrompersi automaticamente perché il sistema operativo ha esaurito la memoria.
- L'attività di cui sopra, pur mantenendo una performance di tutto rispetto per i software in esecuzione.
Ora la domanda principale si riduce a come viene gestita la memoria. Cosa governa esattamente dove risiedono nella memoria i dati appartenenti a un determinato software?
Possibile soluzione 1 : lasciare che i singoli software specifichino esplicitamente l'indirizzo di memoria che useranno nel dispositivo. Supponiamo che Photoshop dichiari che utilizzerà sempre indirizzi di memoria che vanno da 0
a 1023
(immagina la memoria come un array lineare di byte, quindi il primo byte è nella posizione 0
, il 1024
th byte è nella posizione 1023
), ovvero che occupa la 1 GB
memoria. Allo stesso modo, VLC dichiara che occuperà l'intervallo di memoria 1244
per 1876
, ecc.
Vantaggi:
- Ogni applicazione è preassegnata a uno slot di memoria, quindi quando viene installata ed eseguita, memorizza i suoi dati in quell'area di memoria e tutto funziona correttamente.
Svantaggi:
Questo non scala. Teoricamente, un'app potrebbe richiedere un'enorme quantità di memoria quando sta facendo qualcosa di veramente pesante. Quindi, per garantire che non si esaurisca mai la memoria, l'area di memoria assegnata deve essere sempre maggiore o uguale a quella quantità di memoria. E se un software, il cui utilizzo massimo teorico della memoria è 2 GB
(quindi richiede 2 GB
l'allocazione della memoria dalla RAM), è installato in una macchina con solo 1 GB
memoria? Il software dovrebbe semplicemente interrompersi all'avvio, dicendo che la RAM disponibile è inferiore a 2 GB
? O dovrebbe continuare, e nel momento in cui la memoria richiesta supera 2 GB
, interrompere e salvare con il messaggio che non è disponibile memoria sufficiente?
Non è possibile impedire il danneggiamento della memoria. Ci sono milioni di software là fuori, anche se a ciascuno di essi fosse assegnata solo 1 kB
memoria, la memoria totale richiesta sarebbe superiore 16 GB
, che è più di quella offerta dalla maggior parte dei dispositivi. Come possono allora essere assegnati diversi software slot di memoria che non invadono le rispettive aree? In primo luogo, non esiste un mercato del software centralizzato che possa regolare che quando un nuovo software viene rilasciato, deve assegnarsi questa quantità di memoria da quest'area ancora non occupatae in secondo luogo, anche se ci fosse, non è possibile perché il no. di software è praticamente infinito (richiede quindi una memoria infinita per ospitarli tutti), e la RAM totale disponibile su qualsiasi dispositivo non è sufficiente per ospitare anche una frazione di quanto richiesto, rendendo così inevitabile lo sconfinamento dei limiti di memoria di un software su quello di un altro. Che cosa succede quando Photoshop è assegnato posizioni di memoria 1
per 1023
e VLC viene assegnato 1000
a 1676
? Cosa succede se Photoshop memorizza alcuni dati nella posizione 1008
, quindi VLC li sovrascrive con i propri dati e successivamente Photoshopvi accede pensando che siano gli stessi dati precedentemente memorizzati? Come puoi immaginare, accadranno cose brutte.
Quindi chiaramente, come puoi vedere, questa idea è piuttosto ingenua.
Possibile soluzione 2 : proviamo un altro schema, in cui il sistema operativo eseguirà la maggior parte della gestione della memoria. I software, ogni volta che richiedono memoria, richiederanno semplicemente il sistema operativo e il sistema operativo si adatterà di conseguenza. Supponiamo che il sistema operativo assicuri che ogni volta che un nuovo processo richiede memoria, allocherà la memoria dall'indirizzo di byte più basso possibile (come detto in precedenza, la RAM può essere immaginata come un array lineare di byte, quindi per una 4 GB
RAM, l'intervallo di indirizzi per un byte da 0
a2^32-1
) se il processo è in fase di avvio, altrimenti se è un processo in esecuzione che richiede la memoria, verrà allocato dall'ultima posizione di memoria in cui risiede ancora quel processo. Poiché i software emetteranno indirizzi senza considerare quale sarà l'effettivo indirizzo di memoria in cui sono archiviati i dati, il sistema operativo dovrà mantenere una mappatura, per software, dell'indirizzo emesso dal software sull'effettivo indirizzo fisico (Nota: questo è uno dei due motivi per cui chiamiamo questo concetto Virtual Memory
. I software non si preoccupano dell'indirizzo di memoria reale in cui vengono archiviati i loro dati, sputano semplicemente gli indirizzi al volo e il sistema operativo trova il posto giusto per adattarlo e trovarlo successivamente se necessario).
Diciamo che il dispositivo è stato appena acceso, il sistema operativo è appena stato avviato, in questo momento non ci sono altri processi in esecuzione (ignorando il sistema operativo, che è anche un processo!), E decidi di avviare VLC . Quindi a VLC viene assegnata una parte della RAM dagli indirizzi di byte più bassi. Buona. Ora, mentre il video è in esecuzione, è necessario avviare il browser per visualizzare alcune pagine Web. Quindi è necessario avviare il Blocco note per scrivere del testo. E poi Eclipse per fare un po 'di codifica ... Ben presto la tua memoria 4 GB
è completamente esaurita e la RAM ha questo aspetto:
Problema 1: ora non è possibile avviare nessun altro processo, poiché tutta la RAM è esaurita. Quindi i programmi devono essere scritti tenendo presente la massima memoria disponibile (praticamente sarà disponibile ancora meno, poiché anche altri software funzioneranno parallelamente!). In altre parole, non puoi eseguire un'app che consuma molta memoria nel tuo 1 GB
PC sgangherato .
Ok, quindi ora decidi che non è più necessario tenere aperti Eclipse e Chrome , chiudili per liberare un po 'di memoria. Lo spazio occupato nella RAM da quei processi viene recuperato dal sistema operativo e ora appare così:
Supponiamo che chiudendo questi due si liberi 700 MB
spazio - ( 400
+ 300
) MB. Ora devi avviare Opera , che occuperà 450 MB
spazio. Bene, hai più dello 450 MB
spazio disponibile in totale, ma ... non è contiguo, è diviso in blocchi individuali, nessuno dei quali è abbastanza grande da stare 450 MB
. Quindi hai un'idea brillante, spostiamo tutti i processi dal basso al più in alto possibile, il che lascerà lo 700 MB
spazio vuoto in un pezzo in fondo. Questo è chiamatocompaction
. Fantastico, tranne che ... tutti i processi in corso sono in esecuzione. Spostarli significherà spostare l'indirizzo di tutti i loro contenuti (ricorda, il sistema operativo mantiene una mappatura della memoria sputata dal software sull'indirizzo di memoria effettivo. Immagina che il software abbia sputato fuori un indirizzo 45
con i dati 123
e il sistema operativo lo abbia memorizzato nella posizione 2012
e ha creato una voce nella mappa, mappando 45
a 2012
. Se il software è ora spostato in memoria, ciò che era nella posizione 2012
non sarà più 2012
in una posizione, ma in una nuova posizione e il sistema operativo deve aggiornare la mappa di conseguenza per mappare 45
al nuovo indirizzo, in modo che il software possa ottenere i dati attesi ( 123
) quando interroga la posizione di memoria 45
. Per quanto riguarda il software, tutto ciò che sa è quell'indirizzo45
contiene i dati 123
!)! Immagina un processo che fa riferimento a una variabile locale i
. Quando si accede nuovamente, il suo indirizzo è cambiato e non sarà più in grado di trovarlo. Lo stesso varrà per tutte le funzioni, oggetti, variabili, praticamente ogni cosa ha un indirizzo, e spostare un processo significherà cambiare l'indirizzo di tutti loro. Il che ci porta a:
Problema 2: non è possibile spostare un processo. I valori di tutte le variabili, le funzioni e gli oggetti all'interno di quel processo hanno valori hardcoded sputati dal compilatore durante la compilazione, il processo dipende dal fatto che si trovino nella stessa posizione durante la sua vita e cambiarli è costoso. Di conseguenza, i processi lasciano grandi " holes
" quando escono. Questo si chiama
External Fragmentation
.
Bene. Supponi che in qualche modo, in qualche modo miracoloso, riesci a far avanzare i processi. Ora c'è 700 MB
dello spazio libero in basso:
Opera si adatta perfettamente alla parte inferiore. Ora la tua RAM ha questo aspetto:
Buona. Va tutto bene. Tuttavia, non è rimasto molto spazio e ora è necessario avviare nuovamente Chrome , un noto divoratore di memoria! Ha bisogno di molta memoria per iniziare, e non ne hai quasi più ... Tranne .. ora noti che alcuni processi, che inizialmente occupavano un grande spazio, ora non hanno bisogno di molto spazio. Potresti aver interrotto il tuo video in VLC , quindi occupa ancora un po 'di spazio, ma non quanto richiesto durante l'esecuzione di un video ad alta risoluzione. Allo stesso modo per Blocco note e Foto . La tua RAM ora ha questo aspetto:
Holes
, di nuovo! Torna al punto di partenza! Tranne che, in precedenza, i buchi si verificavano a causa della chiusura dei processi, ora è dovuto a processi che richiedono meno spazio rispetto a prima! E hai di nuovo lo stesso problema, il fileholes
resa combinata più spazio del necessario, ma sono sparse in giro, non molto utili in isolamento. Quindi è necessario spostare di nuovo quei processi, un'operazione costosa e molto frequente, poiché i processi si ridurranno spesso di dimensioni nel corso della loro vita.
Problema 3: i processi, nel corso della loro vita, possono ridursi di dimensioni, lasciando spazio inutilizzato che, se necessario, richiederà la costosa operazione di spostamento di molti processi. Questo si chiama
Internal Fragmentation
.
Bene, quindi ora il tuo sistema operativo fa la cosa richiesta, sposta i processi e avvia Chrome e dopo un po 'di tempo, la tua RAM ha questo aspetto:
Freddo. Supponiamo ora di riprendere a guardare Avatar in VLC . Il suo fabbisogno di memoria aumenterà! Ma ... non c'è spazio per crescere, poiché il Blocco note è rannicchiato sul fondo. Quindi, ancora una volta, tutti i processi devono spostarsi di seguito fino a VLC ha trovato spazio sufficiente!
Problema 4: se i processi devono crescere, sarà un'operazione molto costosa
Bene. Supponiamo ora che Foto venga utilizzato per caricare alcune foto da un disco rigido esterno. L'accesso al disco rigido ti porta dal regno delle cache e della RAM a quello del disco, che è più lento di ordini di grandezza. Dolorosamente, irrevocabilmente, trascendentalmente più lento. È un'operazione di I / O, il che significa che non è vincolata alla CPU (è piuttosto l'esatto opposto), il che significa che non ha bisogno di occupare la RAM in questo momento. Tuttavia, occupa ancora ostinatamente la RAM. Se vuoi avviare Firefox nel frattempo, non puoi, perché non c'è molta memoria disponibile, mentre se Foto fosse stata tolta dalla memoria per la durata della sua attività di I / O, avrebbe liberato molta memoria, seguito da una (costosa) compattazione, seguita da Firefox .
Problema 5: i lavori vincolati all'I / O continuano a occupare la RAM, portando a un sottoutilizzo della RAM, che nel frattempo avrebbe potuto essere utilizzata da lavori legati alla CPU.
Quindi, come possiamo vedere, abbiamo tanti problemi anche con l'approccio della memoria virtuale.
Esistono due approcci per affrontare questi problemi - paging
e segmentation
. Parliamone paging
. In questo approccio, lo spazio degli indirizzi virtuale di un processo viene mappato alla memoria fisica in blocchi, chiamati pages
. Una page
dimensione tipica è 4 kB
. La mappatura è mantenuta da qualcosa chiamato a page table
, dato un indirizzo virtuale, tutto ciò che ora dobbiamo fare è scoprire a quale page
indirizzo appartiene, quindi da page table
, trovare la posizione corrispondente per quello page
nella memoria fisica effettiva (nota come frame
), e data che l'offset dell'indirizzo virtuale all'interno di page
è lo stesso per page
così come per frame
, scoprire l'indirizzo effettivo aggiungendo tale offset all'indirizzo restituito da page table
. Per esempio:
A sinistra c'è lo spazio degli indirizzi virtuali di un processo. Supponiamo che lo spazio degli indirizzi virtuali richieda 40 unità di memoria. Se anche lo spazio degli indirizzi fisici (a destra) avesse 40 unità di memoria, sarebbe stato possibile mappare tutte le posizioni da sinistra a una posizione a destra, e saremmo stati così felici. Ma come vorrebbe la sfortuna, non solo la memoria fisica ha meno (24 qui) unità di memoria disponibili, ma deve anche essere condivisa tra più processi! Bene, vediamo come ci arrangiamo.
Quando il processo inizia, supponiamo che 35
venga effettuata una richiesta di accesso alla memoria per la posizione . Qui la dimensione della pagina è 8
(ciascuna page
contiene 8
posizioni, l'intero spazio degli indirizzi virtuali delle 40
posizioni contiene quindi 5
pagine). Quindi questa posizione appartiene alla pagina n. 4
( 35/8
). All'interno di questo page
, questa posizione ha un offset di 3
( 35%8
). Quindi questa posizione può essere specificata dalla tupla (pageIndex, offset)
= (4,3)
. Questo è solo l'inizio, quindi nessuna parte del processo è ancora archiviata nella memoria fisica effettiva. Quindi il page table
, che mantiene una mappatura dalle pagine a sinistra alle pagine effettive a destra (dove vengono chiamateframes
) è attualmente vuoto. Quindi il sistema operativo rinuncia alla CPU, consente a un driver di dispositivo di accedere al disco e recuperare la pagina n. 4
per questo processo (fondamentalmente un pezzo di memoria dal programma sul disco i cui indirizzi vanno da 32
a 39
). Quando arriva, il sistema operativo alloca la pagina da qualche parte nella RAM, ad esempio il primo frame stesso, e page table
per questo processo prende nota che la pagina viene 4
mappata al frame 0
nella RAM. Ora i dati sono finalmente lì nella memoria fisica. Il sistema operativo interroga nuovamente la tabella delle pagine per la tupla (4,3)
e, questa volta, la tabella delle pagine dice che la pagina 4
è già mappata al frame 0
nella RAM. Quindi il sistema operativo va semplicemente al 0
th frame nella RAM, accede ai dati all'offset 3
in quel frame (prenditi un momento per capirlo. L'interopage
, che è stato recuperato dal disco, viene spostato in frame
. Quindi qualunque fosse l'offset di una posizione di memoria individuale in una pagina, sarà lo stesso anche nel frame, poiché all'interno di page
/ frame
, l'unità di memoria risiede ancora nello stesso posto relativamente!) E restituisce i dati! Poiché i dati non sono stati trovati nella memoria alla prima query stessa, ma piuttosto dovevano essere recuperati dal disco per essere caricati in memoria, si tratta di un errore .
Bene. Supponiamo ora che 28
venga effettuato un accesso alla memoria per la posizione . Si riduce a (3,4)
. Page table
in questo momento ha solo una voce, mappatura pagina 4
su frame 0
. Quindi questo è di nuovo un errore , il processo cede la CPU, il driver del dispositivo recupera la pagina dal disco, il processo riprende il controllo della CPU e la sua page table
viene aggiornata. Supponiamo ora che la pagina 3
sia mappata al frame 1
nella RAM. Così (3,4)
diventa (1,4)
, e vengono restituiti i dati in quella posizione nella RAM. Buona. In questo modo, supponiamo che il prossimo accesso alla memoria sia per la posizione 8
, che si traduce in (1,0)
. La pagina 1
non è ancora in memoria, viene ripetuta la stessa procedura e il filepage
frame viene allocato2
nella RAM. Ora la mappatura del processo RAM appare come l'immagine sopra. A questo punto, la RAM, che aveva solo 24 unità di memoria disponibili, è piena. Supponiamo che la successiva richiesta di accesso alla memoria per questo processo provenga dall'indirizzo 30
. Si mappa a (3,6)
, e page table
dice che la pagina 3
è nella RAM, e si mappa al frame 1
. Sìì! Quindi i dati vengono recuperati dalla posizione della RAM (1,6)
e restituiti. Ciò costituisce un successo , poiché i dati richiesti possono essere ottenuti direttamente dalla RAM, essendo quindi molto veloci. Allo stesso modo, i prossimi richieste di accesso pochi, dicono per le posizioni 11
, 32
, 26
, 27
tutti sono colpi , vale a dire i dati richiesti dal processo è situato direttamente nella RAM senza bisogno di guardare altrove.
Supponiamo ora che 3
arrivi una richiesta di accesso alla memoria per la posizione . Essa si traduce in (0,3)
, e page table
per questo processo, che attualmente ha 3 entrate, per le pagine 1
, 3
e 4
dice che questa pagina non è nella memoria. Come i casi precedenti, viene recuperato dal disco, tuttavia, a differenza dei casi precedenti, la RAM è piena! Quindi cosa si fa adesso? Qui sta la bellezza della memoria virtuale, un frame dalla RAM viene sfrattato! (Vari fattori determinano quale frame deve essere sfrattato. Può essere LRU
basato, dove deve essere sfrattato il frame a cui è stato effettuato l'accesso meno di recente per un processo. Può essere la first-come-first-evicted
base, dove viene sfrattato il frame che è stato assegnato più tempo fa, ecc. .) Quindi alcuni frame vengono sfrattati. Pronuncia il fotogramma 1 (scegliendolo casualmente). Tuttavia, questo frame
è associato ad alcunipage
! (Attualmente, è mappato dalla tabella delle pagine alla pagina 3
del nostro unico e solo processo). Quindi a quel processo deve essere raccontata questa tragica notizia, quella frame
, che sfortunatamente ti appartiene, deve essere sfrattata dalla RAM per fare spazio a un'altra pages
. Il processo deve garantire che aggiorni i suoi page table
con queste informazioni, ovvero rimuovendo la voce per quel duo di frame di pagina, in modo che la prossima volta che viene fatta una richiesta per quello page
, dica correttamente al processo che questo page
non è più in memoria e deve essere recuperato dal disco. Buona. Quindi il frame 1
viene espulso, la pagina 0
viene inserita e collocata lì nella RAM e la voce per la pagina 3
viene rimossa e sostituita dalla 0
mappatura della pagina sullo stesso frame1
. Quindi ora la nostra mappatura ha questo aspetto (nota il cambio di colore nel secondo frame
sul lato destro):
Visto cosa è appena successo? Il processo doveva crescere, aveva bisogno di più spazio della RAM disponibile, ma a differenza del nostro scenario precedente in cui ogni processo nella RAM doveva spostarsi per adattarsi a un processo in crescita, qui è successo con una sola page
sostituzione! Ciò è stato reso possibile dal fatto che la memoria per un processo non ha più bisogno di essere contigua, può risiedere in punti diversi in blocchi, il sistema operativo mantiene le informazioni su dove si trovano e, quando richiesto, vengono opportunamente interrogate. Nota: potresti pensare, eh, cosa succede se la maggior parte delle volte è a miss
, e i dati devono essere caricati costantemente dal disco nella memoria? Sì, in teoria è possibile, ma la maggior parte dei compilatori sono progettati in modo tale che seguelocality of reference
, cioè se vengono utilizzati i dati da una posizione di memoria, i dati successivi necessari si troveranno da qualche parte molto vicino, forse dallo stesso page
, page
che è stato appena caricato in memoria. Di conseguenza, il prossimo errore si verificherà dopo un po 'di tempo, la maggior parte dei requisiti di memoria imminenti saranno soddisfatti dalla pagina appena inserita o dalle pagine già in memoria che sono state utilizzate di recente. Lo stesso identico principio ci permette di sfrattare anche quello usato meno di recente page
, con la logica che ciò che non è stato usato da un po ', probabilmente non verrà usato anche da un po'. Tuttavia, non è sempre così e, in casi eccezionali, sì, le prestazioni potrebbero risentirne. Ne parleremo più avanti.
Soluzione al problema 4: i processi ora possono crescere facilmente, se il problema di spazio viene affrontato, tutto ciò che serve è fare una semplice page
sostituzione, senza spostare nessun altro processo.
Soluzione al problema 1: un processo può accedere a memoria illimitata. Quando è necessaria più memoria di quella disponibile, il disco viene utilizzato come backup, i nuovi dati richiesti vengono caricati in memoria dal disco e i dati utilizzati meno di recente frame
(o page
) vengono spostati su disco. Questo può andare avanti all'infinito e poiché lo spazio su disco è economico e virtualmente illimitato, dà l'illusione di una memoria illimitata. Un altro motivo per il nome Virtual Memory
, ti dà l'illusione di una memoria che non è realmente disponibile!
Freddo. In precedenza stavamo affrontando un problema in cui, anche se un processo si riduce di dimensioni, lo spazio vuoto è difficile da recuperare con altri processi (perché richiederebbe una costosa compattazione). Ora è facile, quando un processo diventa di dimensioni più piccole, molti dei suoi pages
non vengono più utilizzati, quindi quando altri processi richiedono più memoria, un semplice LRU
sfratto basato elimina automaticamente quelli meno utilizzati pages
dalla RAM e li sostituisce con le nuove pagine di gli altri processi (e ovviamente l'aggiornamento page tables
di tutti quei processi così come il processo originale che ora richiede meno spazio), tutti questi senza alcuna costosa operazione di compattazione!
Soluzione al problema 3: ogni volta che le dimensioni dei processi si riducono, la sua frames
RAM sarà meno utilizzata, quindi un semplice LRU
sfratto basato può eliminare quelle pagine e sostituirle con quelle pages
richieste da nuovi processi, evitando così Internal Fragmentation
senza necessità compaction
.
Per quanto riguarda il problema 2, prenditi un momento per capirlo, lo scenario stesso è completamente rimosso! Non è necessario spostare un processo per adattarlo a un nuovo processo, perché ora l'intero processo non deve mai adattarsi contemporaneamente, solo alcune pagine devono adattarsi ad hoc, ciò avviene tramite lo sfratto frames
dalla RAM. Tutto accade in unità di pages
, quindi non esiste il concetto di hole
adesso, e quindi non si tratta di nulla in movimento! Può essere 10 pages
dovuto essere spostato a causa di questo nuovo requisito, ce ne sono migliaia pages
rimasti intatti. Considerando che, in precedenza, tutti i processi (ogni bit) dovevano essere spostati!
Soluzione al problema 2: per accogliere un nuovo processo, i dati provenienti solo da parti di altri processi utilizzate meno di recente devono essere rimossi come richiesto, e ciò accade in unità di dimensioni fisse chiamate pages
. Quindi non c'è possibilità di hole
o External Fragmentation
con questo sistema.
Ora, quando il processo deve eseguire alcune operazioni di I / O, può rinunciare facilmente alla CPU! Il sistema operativo semplicemente sfrutta tutto il suo pages
dalla RAM (forse lo memorizza in qualche cache) mentre i nuovi processi occupano la RAM nel frattempo. Quando l'operazione di I / O è terminata, il sistema operativo ripristina semplicemente quelli pages
nella RAM (ovviamente sostituendo il pages
da alcuni altri processi, può essere da quelli che hanno sostituito il processo originale, o può essere da alcuni che a loro volta devono eseguire I / Oh ora, e quindi puoi rinunciare alla memoria!)
Soluzione al problema 5: quando un processo esegue operazioni di I / O, può facilmente rinunciare all'utilizzo della RAM, che può essere utilizzata da altri processi. Ciò porta a un corretto utilizzo della RAM.
E, naturalmente, ora nessun processo accede direttamente alla RAM. Ogni processo accede a una posizione di memoria virtuale, che è mappata a un indirizzo RAM fisico e mantenuta dal page-table
di quel processo. La mappatura è supportata dal sistema operativo, il sistema operativo consente al processo di sapere quale frame è vuoto in modo che una nuova pagina per un processo possa essere adattata lì. Poiché questa allocazione di memoria è supervisionata dal sistema operativo stesso, può facilmente garantire che nessun processo invada i contenuti di un altro processo allocando solo frame vuoti dalla RAM, o invadendo i contenuti di un altro processo nella RAM, comunichi al processo per aggiornarlo page-table
.
Soluzione al problema originale: non è possibile che un processo acceda ai contenuti di un altro processo, poiché l'intera allocazione è gestita dal sistema operativo stesso e ogni processo viene eseguito nel proprio spazio di indirizzi virtuali sandbox.
Quindi paging
(tra le altre tecniche), insieme alla memoria virtuale, è ciò che alimenta i software odierni in esecuzione su sistemi operativi! Ciò libera lo sviluppatore del software dalla preoccupazione di quanta memoria è disponibile sul dispositivo dell'utente, dove memorizzare i dati, come impedire che altri processi corrompano i dati del proprio software, ecc. Tuttavia, ovviamente, non è completamente a prova. Ci sono difetti:
Paging
è, in definitiva, dare all'utente l'illusione di una memoria infinita utilizzando il disco come backup secondario. Il recupero dei dati dalla memoria secondaria per adattarli alla memoria (chiamato page swap
e viene chiamato l'evento di non trovare la pagina desiderata nella RAM page fault
) è costoso in quanto si tratta di un'operazione di I / O. Questo rallenta il processo. Molti di questi scambi di pagina avvengono in successione e il processo diventa estremamente lento. Hai mai visto il tuo software funzionare bene e alla moda, e improvvisamente diventa così lento che quasi si blocca o non ti lascia alcuna opzione che lo riavvii? Forse si stavano verificando troppi scambi di pagina, rendendolo lento (chiamato thrashing
).
Quindi tornando a OP,
Perché abbiamo bisogno della memoria virtuale per eseguire un processo? - Come spiega a lungo la risposta, per dare ai software l'illusione che il dispositivo / sistema operativo abbia una memoria infinita, in modo che qualsiasi software, grande o piccolo, possa essere eseguito, senza preoccuparsi dell'allocazione della memoria, o altri processi che ne corrompono i dati, anche quando correre in parallelo. Si tratta di un concetto, implementato nella pratica attraverso varie tecniche, una delle quali, come qui descritto, è Paging . Potrebbe anche essere Segmentazione .
Dove si trova questa memoria virtuale quando il processo (programma) dal disco rigido esterno viene portato nella memoria principale (memoria fisica) per l'esecuzione? - La memoria virtuale non sta da nessuna parte di per sé, è un'astrazione, sempre presente, quando il software / processo / programma viene avviato, viene creata una nuova tabella di pagine e contiene la mappatura dagli indirizzi sputi da quella processo nell'effettivo indirizzo fisico nella RAM. Poiché gli indirizzi sputati dal processo non sono indirizzi reali, in un certo senso sono, in realtà, ciò che puoi dire the virtual memory
.
Chi si prende cura della memoria virtuale e qual è la dimensione della memoria virtuale? - Si occupa, in tandem, del sistema operativo e del software. Immagina una funzione nel tuo codice (che alla fine è stato compilato e trasformato nell'eseguibile che ha generato il processo) che contiene una variabile locale - un file int i
. Quando il codice viene eseguito, i
ottiene un indirizzo di memoria all'interno dello stack della funzione. Quella funzione è essa stessa memorizzata come oggetto da qualche altra parte. Questi indirizzi sono generati dal compilatore (il compilatore che ha compilato il codice nell'eseguibile) - indirizzi virtuali. Quando viene eseguito, i
deve risiedere da qualche parte nell'indirizzo fisico effettivo per la durata di quella funzione almeno (a meno che non sia una variabile statica!), Quindi il sistema operativo mappa l'indirizzo virtuale generato dal compilatore dii
in un indirizzo fisico effettivo, in modo che ogni volta che, all'interno di quella funzione, un codice richiede il valore di i
, quel processo può interrogare il sistema operativo per quell'indirizzo virtuale e il sistema operativo a sua volta può interrogare l'indirizzo fisico per il valore memorizzato e restituirlo.
Supponiamo che se la dimensione della RAM è 4 GB (cioè 2 ^ 32-1 spazi di indirizzi) qual è la dimensione della memoria virtuale? - La dimensione della RAM non è correlata alla dimensione della memoria virtuale, dipende dal sistema operativo. Ad esempio, su Windows a 32 bit, lo è 16 TB
, su Windows a 64 bit, lo è 256 TB
. Naturalmente, è anche limitato dalla dimensione del disco, poiché è lì che viene eseguito il backup della memoria.