Un giorno è divertente guardare il livello superficiale dell'esperienza di elaborazione, e altri giorni è divertente approfondire il funzionamento interno. Oggi diamo uno sguardo alla struttura della memoria del computer e alla quantità di cose che puoi impacchettare in un bastoncino di RAM.
La sessione di domande e risposte di oggi ci arriva per gentile concessione di SuperUser, una suddivisione di Stack Exchange, un raggruppamento guidato dalla comunità di siti web di domande e risposte.
La domanda
Il lettore SuperUser Johan Smohan è alle prese con il modo in cui il tipo di processore e la dimensione della memoria lavorano insieme per produrre un numero totale di indirizzi. Lui scrive:
Quanti indirizzi di memoria possiamo ottenere con un processore a 32 bit e 1 GB di ram e quanti con un processore a 64 bit?
Penso che sia qualcosa del genere:
1 GB di RAM diviso per 32 bit 4 bit (?) Per ottenere il numero di indirizzi di memoria?
Ho letto su Wikipedia che 1 indirizzo di memoria è largo 32 bit o 4 ottetti (1 ottetto = 8 bit), rispetto a un processore a 64 bit in cui 1 indirizzo di memoria o 1 intero è largo 64 bit o 8 ottetti. Ma non so nemmeno se l'ho capito correttamente.
Questi sono i tipi di domande che possono tenere sveglio la notte un curioso smanettone. Quanti indirizzi sono disponibili in ciascuno degli ipotetici sistemi di Johan?
La risposta
Il collaboratore di SuperUser Gronostaj offre alcune informazioni su come la RAM è suddivisa e utilizzata:
Risposta breve: Il numero di indirizzi disponibili è uguale al minore tra quelli:
- Dimensioni della memoria in byte
- Il più grande numero intero senza segno che può essere salvato nella parola macchina della CPU
Risposta lunga e spiegazione di quanto sopra:
La memoria è composta da byte (B). Ogni byte è composto da 8 bit (b).
1 B = 8 b1 GB di RAM è in realtà 1 GiB (gibibyte, non gigabyte). La differenza è:
1 GB = 10 ^ 9 B = 1.000.000.000 B 1 GiB = 2 ^ 30 B = 1073 741 824 BOgni byte di memoria ha il proprio indirizzo, non importa quanto sia grande la parola macchina della CPU. Per esempio. La CPU Intel 8086 era a 16 bit e indirizzava la memoria per byte, così come le moderne CPU a 32 e 64 bit. Questa è la causa del primo limite: non puoi avere più indirizzi di byte di memoria.
L'indirizzo di memoria è solo un numero di byte che la CPU deve saltare dall'inizio della memoria per arrivare a quello che sta cercando.
- Per accedere al primo byte deve saltare 0 byte, quindi l'indirizzo del primo byte è 0.
- Per accedere al secondo byte deve saltare 1 byte, quindi il suo indirizzo è 1.
- (e così via…)
- Per accedere all'ultimo byte, la CPU salta 1073741823 byte, quindi il suo indirizzo è 1073741823.
Ora devi sapere cosa significa effettivamente 32 bit. Come ho detto prima, ha le dimensioni di una parola macchina.
La parola macchina è la quantità di memoria utilizzata dalla CPU per contenere i numeri (nella RAM, nella cache o nei registri interni). La CPU a 32 bit utilizza 32 bit (4 byte) per contenere i numeri. Anche gli indirizzi di memoria sono numeri, quindi su una CPU a 32 bit l'indirizzo di memoria è composto da 32 bit.
Ora pensa a questo: se hai un bit, puoi salvare due valori su di esso: 0 o 1. Aggiungi un altro bit e avrai quattro valori: 0, 1, 2, 3. Su tre bit, puoi salvare otto valori : 0, 1, 2… 6, 7. Questo è in realtà un sistema binario e funziona così:
Decimale binario 0 0000 1 0001 2 0010 3 0011 4 0100 5 0101 6 0110 7 0111 8 1000 9 1001 10 1010 11 1011 12 1100 13 1101 14 1110 15 1111Funziona esattamente come la solita addizione, ma la cifra massima è 1, non 9. Lo 0 decimale è
0000, quindi aggiungi 1 e ottieni0001, aggiungine uno ancora una volta e il gioco è fatto0010. Quello che è successo qui è come avere i decimali09e aggiungendo uno: si cambia 9 in 0 e si incrementa la cifra successiva.Dall'esempio sopra puoi vedere che c'è sempre un valore massimo che puoi mantenere in un numero con numero costante di bit - perché quando tutti i bit sono 1 e provi ad aumentare il valore di 1, tutti i bit diventeranno 0, interrompendo così il numero. Si chiama integer overflow e causa molti spiacevoli problemi, sia per gli utenti che per gli sviluppatori.
11111111 = 255 + 1 ----------- 100000000 = 0 (9 bit qui, quindi 1 viene tagliato)
- Per 1 bit il valore massimo è 1,
- 2 bit - 3,
- 3 bit - 7,
- 4 bit - 15
Il numero massimo possibile è sempre 2 ^ N-1, dove N è il numero di bit. Come ho detto prima, un indirizzo di memoria è un numero e ha anche un valore massimo. Ecco perché la dimensione della parola macchina è anche un limite per il numero di indirizzi di memoria disponibili: a volte la tua CPU non è in grado di elaborare numeri abbastanza grandi da indirizzare più memoria.
Quindi su 32 bit puoi mantenere numeri da 0 a 2 ^ 32-1, e questo è 4 294 967 295. È più dell'indirizzo più grande in 1 GB di RAM, quindi nel tuo caso specifico la quantità di RAM sarà il fattore limitante.
Il limite di RAM per la CPU a 32 bit è teoricamente di 4 GB (2 ^ 32) e per la CPU a 64 bit è di 16 EB (exabyte, 1 EB = 2 ^ 30 GB). In altre parole, la CPU a 64 bit potrebbe indirizzare l'intera Internet ... 200 volte;) (stimato da Wolfram Alpha ).
Tuttavia, nei sistemi operativi reali, le CPU a 32 bit possono indirizzare circa 3 GiB di RAM. Ciò è dovuto all'architettura interna del sistema operativo: alcuni indirizzi sono riservati per altri scopi. Puoi leggere di più su questo cosiddetto 3 GB barrier on Wikipedia . Puoi aumentare questo limite con Estensione indirizzo fisico .
Parlando di indirizzamento della memoria, ci sono alcune cose che dovrei menzionare: memoria virtuale , segmentazione e impaginazione .
Memoria virtuale
Come ha sottolineato @Daniel R Hicks in un'altra risposta, i sistemi operativi utilizzano la memoria virtuale. Ciò significa che le applicazioni in realtà non funzionano su indirizzi di memoria reali, ma su quelli forniti dal sistema operativo.
Questa tecnica consente al sistema operativo di spostare alcuni dati dalla RAM a un cosiddetto Pagefile (Windows) o Swap (* NIX). L'HDD è di alcune magnitudini più lento della RAM, ma non è un problema serio per i dati a cui si accede raramente e consente al sistema operativo di fornire alle applicazioni più RAM di quella effettivamente installata.
Paging
Quello di cui stavamo parlando finora è chiamato schema di indirizzamento piatto.
Il paging è uno schema di indirizzamento alternativo che consente di indirizzare più memoria che normalmente con una parola macchina nel modello flat.
Immagina un libro pieno di parole di 4 lettere. Supponiamo che ci siano 1024 numeri su ogni pagina. Per indirizzare un numero, devi sapere due cose:
- Il numero di pagina su cui è stampata quella parola.
- Quale parola in quella pagina è quella che stai cercando.
Questo è esattamente il modo in cui le moderne CPU x86 gestiscono la memoria. È diviso in 4 pagine KiB (1024 parole macchina ciascuna) e quelle pagine hanno numeri. (in realtà le pagine possono anche essere grandi 4 MiB o 2 MiB con PAE ). Quando si desidera indirizzare la cella di memoria, è necessario il numero di pagina e l'indirizzo in quella pagina. Nota che ogni cella di memoria è referenziata da esattamente una coppia di numeri, questo non sarà il caso della segmentazione.
Segmentazione
Bene, questo è abbastanza simile al paging. È stato utilizzato in Intel 8086, solo per citare un esempio. I gruppi di indirizzi sono ora chiamati segmenti di memoria, non pagine. La differenza è che i segmenti possono sovrapporsi e si sovrappongono molto. Ad esempio, su 8086 la maggior parte delle celle di memoria erano disponibili da 4096 segmenti diversi.
Un esempio:
Supponiamo di avere 8 byte di memoria, tutti contenenti zeri tranne il 4 ° byte che è uguale a 255.
Illustrazione per il modello a memoria piatta:
_____ | 0 | | 0 | | 0 | | 255 | | 0 | | 0 | | 0 | | 0 | -----Illustrazione per la memoria impaginata con pagine da 4 byte:
PAGE0 _____ | 0 | | 0 | | 0 | PAGINA 1 | 255 | _____ ----- | 0 | | 0 | | 0 | | 0 | -----Illustrazione per la memoria segmentata con segmenti di 4 byte spostati di 1:
SEG 0 _____ SEG 1 | 0 | _____ SEG 2 | 0 | | 0 | _____ SEG 3 | 0 | | 0 | | 0 | _____ SEG 4 | 255 | | 255 | | 255 | | 255 | _____ SEG 5 ----- | 0 | | 0 | | 0 | | 0 | _____ SEG 6 ----- | 0 | | 0 | | 0 | | 0 | _____ SEG 7 ----- | 0 | | 0 | | 0 | | 0 | _____ ----- | 0 | | 0 | | 0 | | 0 | ----- ----- ----- -----Come puoi vedere, il quarto byte può essere indirizzato in quattro modi: (indirizzamento da 0)
- Segmento 0, offset 3
- Segmento 1, offset 2
- Segmento 2, offset 1
- Segmento 3, offset 0
È sempre la stessa cella di memoria.
Nelle implementazioni reali i segmenti vengono spostati di più di 1 byte (per 8086 era di 16 byte).
La cosa brutta della segmentazione è che è complicata (ma penso che tu lo sappia già;) Quello che è buono è che puoi usare alcune tecniche intelligenti per creare programmi modulari.
Ad esempio, puoi caricare un modulo in un segmento, quindi fingere che il segmento sia più piccolo di quanto non sia in realtà (abbastanza piccolo da contenere il modulo), quindi scegliere il primo segmento che non si sovrappone a quello pseudo-più piccolo e caricare il successivo modulo e così via. Fondamentalmente, ciò che ottieni in questo modo sono pagine di dimensioni variabili.
Hai qualcosa da aggiungere alla spiegazione? Suona nei commenti. Vuoi leggere altre risposte da altri utenti esperti di tecnologia Stack Exchange? Dai un'occhiata al thread di discussione completo qui .