Hur många minnesadresser kan RAM-minne i min dator hållas?
Somedays är det roligt att titta på ytbehandlingen av datorupplevelsen, och andra dagar är det kul att gräva rätt in i det inre arbetet. Idag tar vi en titt på strukturen i datorns minne och hur mycket du kan packa i en RAM-minne.
Dagens Question & Answer-session kommer till oss med tillstånd av SuperUser-en indelning av Stack Exchange, en community-driven gruppering av Q & A-webbplatser.
Frågan
SuperUser-läsaren Johan Smohan bryter med hur processortyp och minnesstorlek fungerar tillsammans för att ge ett totalt antal adresser. Han skriver:
Hur många minnesadresser kan vi få med en 32-bitars processor och 1GB ram och hur många med en 64-bitars processor?
Jag tycker att det är något så här:
1 GB ram dividerad med antingen 32 bitar 4 bitar (?) För att få antalet minnesadresser?
Jag läser på Wikipedia att 1 minnesadresser är 32 bitar breda eller 4 oktetter (1 oktet = 8 bitar), jämfört med en 64 bitars processor där 1 minnesadresser eller 1 heltal är 64 bitars breda eller 8 oktetter. Men vet inte om jag förstår det rätt heller.
Det här är de typer av frågor som kan hålla en nyfiken geek upp på natten. Hur många adresser finns tillgängliga under varje av Johans hypotetiska system?
Svaret
SuperUser-bidragsgivaren Gronostaj erbjuder viss inblick i hur RAM: n är uppdelad och utnyttjad:
Kort svar: Antalet tillgängliga adresser är lika med de mindre av dessa:
- Minnesstorlek i byte
- Storaste usignerade heltal som kan sparas i CPUs maskinord
Långt svar och förklaring av ovanstående:
Minne består av byte (B). Varje byte består av 8 bitar (b).
1 B = 8 b
1 GB RAM är faktiskt 1 GiB (gibibyte, inte gigabyte). Skillnaden är:
1 GB = 10 ^ 9 B = 1 000 000 000 B 1 GiB = 2 ^ 30 B = 1 073 741 824 B
Varje minnesbyte har sin egen adress, oavsett hur stor CPU-maskinordet är. T.ex. Intel 8086-CPU var 16-bitars och den adresserade minnet av byte, så gör moderna 32-bitars och 64-bitars CPU: er. Det är orsaken till den första gränsen - du kan inte ha fler adresser än minnesbyte.
Minnesadressen är bara ett antal byte som CPU: n måste hoppa över från början av minnet för att komma till den som den letar efter.
- För att komma åt den första byten måste den hoppa över 0 byte, så första bytes adress är 0.
- För att komma åt den andra byten måste den hoppa över 1 byte, så adressen är 1.
- (och så vidare… )
- För att komma åt den sista byten går CPU 1073741823 byte, så adressen är 1073741823.
Nu måste du veta vad 32-bit betyder egentligen. Som jag nämnde tidigare är det storleken på ett maskinord.
Maskinord är mängden minne som CPU använder för att hålla nummer (i RAM, cache eller interna register). 32-bitars CPU använder 32 bitar (4 byte) för att hålla nummer. Minnesadresser är siffror, så på en 32-bitars CPU innehåller minnesadressen 32 bitar.
Tänk nu på det här: Om du har en bit kan du spara två värden på den: 0 eller 1. Lägg till en bit och du har fyra värden: 0, 1, 2, 3. På tre bitar kan du spara åtta värden : 0, 1, 2 ... 6, 7. Detta är faktiskt ett binärt system och det fungerar så:
Binärt decimalt 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 1111
Det fungerar precis som vanligt tillägg, men den maximala siffran är 1, inte 9. Decimal 0 är
0000
, då lägger du till 1 och får0001
, lägg till en gång till och du har0010
. Vad som händer här är som att ha decimal09
och lägg till en: du ändrar 9 till 0 och ökar nästa siffra.Från exemplet ovan kan du se att det alltid finns ett maximivärde som du kan behålla i ett antal med konstant antal bitar - för när alla bitar är 1 och du försöker öka värdet med 1 blir alla bitar 0, vilket bryter mot siffra. Det kallas heltal överflöde och orsakar många obehagliga problem, både för användare och utvecklare.
11111111 = 255 + 1 ----------- 100000000 = 0 (9 bitar här, så 1 är trimmad)
- För 1 bit är det största värdet 1,
- 2 bitar - 3,
- 3 bitar - 7,
- 4 bitar - 15
Det största möjliga talet är alltid 2 ^ N-1, där N är antalet bitar. Som jag sa tidigare är en minnesadress ett tal och det har också ett maximalt värde. Därför är maskinordets storlek också en gräns för antalet tillgängliga minnesadresser - ibland kan din CPU inte bara hantera tal som är tillräckligt stora för att hantera mer minne.
Så på 32 bitar kan du hålla siffror från 0 till 2 ^ 32-1 och det är 4 294 967 295. Det är mer än den största adressen i 1 GB RAM, så i ditt specifika fall kommer RAM-värdet att vara den begränsande faktorn.
RAM-gränsen för 32-bitars CPU är teoretiskt 4 GB (2 ^ 32) och för 64-bitars CPU är det 16 EB (exabytes, 1 EB = 2 ^ 30 GB). Med andra ord kan 64-bitars CPU adressera hela Internet ... 200 gånger;) (uppskattad av WolframAlpha).
I verkliga operativsystem kan 32-bitars CPU-adresser emellertid adressera omkring 3 GiB RAM. Det beror på operativsystemets interna arkitektur - vissa adresser är reserverade för andra ändamål. Du kan läsa mer om detta så kallade 3 GB-hinder på Wikipedia. Du kan häva denna gräns med fysisk adressförlängning.
När det gäller minnesadressering finns det få saker jag bör nämna: virtuellt minne, segmentering och personsökning.
Virtuellt minne
Som @ Daniel R Hicks påpekade i ett annat svar använder OSes virtuellt minne. Vad det betyder är att applikationer faktiskt inte fungerar på riktiga minnesadresser, men de som tillhandahålls av OS.
Med den här tekniken kan operativsystemet flytta vissa data från RAM till en så kallad Pagefile (Windows) eller Swap (* NIX). HDD är få storheter långsammare än RAM, men det är inte ett allvarligt problem för sällan tillgång till data och det gör att OS kan ge applikationer mer RAM än vad du faktiskt har installerat.
personsökning
Vad vi talade om hittills kallas platt adresseringssystem.
Paging är ett alternativt adresseringsschema som tillåter att hantera mer minne som du normalt kunde med ett maskinord i platt modell.
Föreställ dig en bok fylld med 4 bokstäver. Låt oss säga att det finns 1024 nummer på varje sida. För att adressera ett nummer måste du veta två saker:
- Antalet sidor på vilket det ordet skrivs ut.
- Vilket ord på den sidan är den du letar efter.
Nu är det exakt hur moderna x86-processorer hanterar minnet. Den är uppdelad i 4 KiB-sidor (1024 maskinord varje) och de sidorna har siffror. (faktiskt sidor kan också vara 4 MiB stora eller 2 MiB med PAE). När du vill adressera minnescellen behöver du sidnumret och adressen på den sidan. Observera att varje minnescell refereras av exakt ett par nummer, det kommer inte att vara fallet för segmentering.
segmente~~POS=TRUNC
Tja, den här är ganska lik sökning. Den användes i Intel 8086, bara för att nämna ett exempel. Grupper av adresser kallas nu minnesegment, inte sidor. Skillnaden är att segment kan överlappa varandra, och de överlappar mycket. Till exempel på 8086 var de flesta minnesceller tillgängliga från 4096 olika segment.
Ett exempel:
Låt oss säga att vi har 8 byte minne, alla med nollor utom för 4: e byte som är lika med 255.
Illustration för platt minnesmodell:
_____ | 0 | | 0 | | 0 | | 255 | | 0 | | 0 | | 0 | | 0 | -----
Illustration för paged minne med 4-byte sidor:
PAGE0 _____ | 0 | | 0 | | 0 | PAGE1 | 255 | _____ ----- | 0 | | 0 | | 0 | | 0 | -----
Illustration för segmenterat minne med 4-bytesegment skiftat med 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 | ----- ----- ----- -----
Som du kan se kan fjärde byte adresseras på fyra sätt: (adressering från 0)
- Segment 0, förskjutning 3
- Segment 1, förskjutning 2
- Segment 2, förskjutning 1
- Segment 3, förskjutna 0
Det är alltid samma minnescell.
I verkliga implementeringar förskjuts segmenten med mer än 1 byte (för 8086 var det 16 byte).
Vad som är dåligt om segmentering är att det är komplicerat (men jag tror att du redan vet det;) Det är bra att du kan använda några kloka tekniker för att skapa modulära program.
Du kan till exempel ladda en modul till ett segment och låtsas att segmentet är mindre än det egentligen är (bara tillräckligt liten för att hålla modulen), välj sedan det första segmentet som inte överlappar den pseudo-mindre och ladda sedan modul, och så vidare. I grund och botten, vad du får på detta sätt är sidor med variabel storlek.
Har du något att lägga till förklaringen? Ljud av i kommentarerna. Vill du läsa mer svar från andra tech-savvy Stack Exchange-användare? Kolla in hela diskussionsgängan här.