คำตอบสั้น ๆ :จำนวนที่อยู่ที่มีอยู่มีค่าน้อยกว่าที่อยู่เหล่านี้:
- ขนาดหน่วยความจำในหน่วยไบต์
- จำนวนเต็มที่ไม่ได้ลงนามที่ยิ่งใหญ่ที่สุดที่สามารถบันทึกในคำของเครื่อง CPU
คำตอบยาวและคำอธิบายข้างต้น:
หน่วยความจำประกอบด้วยไบต์ (B) แต่ละไบต์ประกอบด้วย 8 บิต (b)
1 B = 8 b
RAM 1 GB เป็นจริง 1 GiB (gibibyte ไม่ใช่กิกะไบต์) ความแตกต่างคือ:
1 GB = 10^9 B = 1 000 000 000 B
1 GiB = 2^30 B = 1 073 741 824 B
หน่วยความจำทุกไบต์มีที่อยู่ของตัวเองไม่ว่าคำของเครื่อง CPU จะใหญ่เพียงใด เช่น. Intel 8086 CPU เป็น 16 บิตและเป็นหน่วยความจำที่มีหน่วยเป็นไบต์ดังนั้น CPU แบบ 32 บิตและ 64 บิตที่ทันสมัย นั่นเป็นสาเหตุของการ จำกัด ครั้งแรก - คุณไม่สามารถมีที่อยู่มากกว่าไบต์หน่วยความจำได้
ที่อยู่หน่วยความจำเป็นจำนวนไบต์ที่ CPU ต้องข้ามจากจุดเริ่มต้นของหน่วยความจำเพื่อไปยังที่อยู่ที่ต้องการ
- ในการเข้าถึงไบต์แรกนั้นจะต้องข้าม 0 ไบต์ดังนั้นที่อยู่ไบต์แรกคือ 0
- ในการเข้าถึงไบต์ที่สองจะต้องข้าม 1 ไบต์ดังนั้นที่อยู่ของมันคือ 1
- (และอื่น ๆ ... )
- หากต้องการเข้าถึงไบต์สุดท้าย CPU จะข้าม 1073741823 ไบต์ดังนั้นที่อยู่ของมันคือ 1073741823
ตอนนี้คุณต้องรู้ว่าจริง ๆ แล้ว 32- บิตหมายความว่าอย่างไร ดังที่ฉันได้กล่าวไว้ก่อนหน้านี้มันเป็นขนาดของคำศัพท์ของเครื่องจักร
Machine word คือจำนวนหน่วยความจำของ CPU ที่ใช้เพื่อเก็บหมายเลข (ใน RAM, แคชหรือรีจิสเตอร์ภายใน) CPU แบบ 32 บิตใช้ 32 บิต (4 ไบต์) เพื่อเก็บหมายเลข ที่อยู่หน่วยความจำก็เป็นตัวเลขเช่นกันดังนั้นบน CPU แบบ 32 บิตที่อยู่หน่วยความจำประกอบด้วย 32 บิต
ตอนนี้คิดเกี่ยวกับสิ่งนี้: ถ้าคุณมีหนึ่งบิตคุณสามารถบันทึกสองค่าในนั้น: 0 หรือ 1 เพิ่มอีกหนึ่งบิตและคุณมีสี่ค่า: 0, 1, 2, 3 ในสามบิตคุณสามารถบันทึกแปดค่า : 0, 1, 2 ... 6, 7 นี่คือระบบไบนารีจริง ๆ และมันทำงานแบบนั้น:
Decimal Binary
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
มันทำงานได้เหมือนกันนอกจากนี้ปกติ แต่หลักสูงสุดคือ 1 ไม่ 9. สิบ 0 0000
แล้วคุณเพิ่ม 1 และได้รับเพิ่มอีกครั้งหนึ่งและคุณมี0001
0010
สิ่งที่เกิดขึ้นที่นี่เหมือนกับการมีทศนิยม09
และเพิ่ม: คุณเปลี่ยน 9 เป็น 0 และเพิ่มตัวเลขถัดไป
จากตัวอย่างข้างต้นคุณจะเห็นว่ามีค่าสูงสุดเสมอคุณสามารถเก็บไว้ในจำนวนที่มีจำนวนบิตคงที่ - เพราะเมื่อบิตทั้งหมดเป็น 1 และคุณพยายามที่จะเพิ่มมูลค่าโดย 1 บิตทั้งหมดจะกลายเป็น 0 จึงทำลาย จำนวน. มันเรียกว่าจำนวนเต็มล้นและทำให้เกิดปัญหาที่ไม่พึงประสงค์มากมายทั้งสำหรับผู้ใช้และนักพัฒนา
11111111 = 255
+ 1
-----------
100000000 = 0 (9 bits here, so 1 is trimmed)
- สำหรับ 1 บิตค่ายิ่งใหญ่ที่สุดคือ 1
- 2 บิต - 3
- 3 บิต - 7
- 4 บิต - 15
จำนวนที่มากที่สุดที่เป็นไปได้คือ 2 ^ N-1 โดยที่ N คือจำนวนบิต อย่างที่ฉันได้กล่าวไปแล้วที่อยู่หน่วยความจำคือตัวเลขและยังมีค่าสูงสุด นั่นเป็นสาเหตุที่ขนาดของเครื่องคำ จำกัด จำนวนที่อยู่หน่วยความจำที่มีอยู่ด้วย - บางครั้ง CPU ของคุณก็ไม่สามารถประมวลผลตัวเลขที่ใหญ่พอที่จะรองรับหน่วยความจำเพิ่มเติม
ดังนั้นใน 32 บิตคุณสามารถเก็บตัวเลขได้ตั้งแต่ 0 ถึง 2 ^ 32-1 และนั่นคือ 4 294 967 295 มันเป็นมากกว่าที่อยู่ที่ยิ่งใหญ่ที่สุดใน RAM ขนาด 1 GB ดังนั้นในกรณีของ RAM จำนวนเฉพาะของคุณจะเป็นปัจจัย จำกัด
ขีด จำกัด RAM สำหรับ CPU แบบ 32 บิตในทางทฤษฎีแล้ว 4 GB (2 ^ 32) และสำหรับ 64 บิต CPU นั้นมีขนาด 16 EB (exabytes, 1 EB = 2 ^ 30 GB) กล่าวอีกนัยหนึ่งซีพียู 64 บิตสามารถตอบสนองอินเทอร์เน็ตทั้งหมด ... 200 ครั้ง;) (ประเมินโดยWolframAlpha )
อย่างไรก็ตามในระบบปฏิบัติการจริงซีพียู 32 บิตสามารถจัดการกับ RAM ได้ประมาณ 3 GiB นั่นเป็นเพราะสถาปัตยกรรมภายในของระบบปฏิบัติการ - ที่อยู่บางส่วนถูกสงวนไว้สำหรับวัตถุประสงค์อื่น คุณสามารถอ่านเพิ่มเติมเกี่ยวกับเรื่องนี้ที่เรียกว่า3 GB อุปสรรคในวิกิพีเดีย คุณสามารถยกขีด จำกัด นี้กับทางกายภาพที่อยู่ส่วนขยาย
พูดเกี่ยวกับหน่วยความจำที่อยู่, มีบางสิ่งที่ฉันควรจะพูดถึง: หน่วยความจำเสมือน , การแบ่งส่วนและเพจ
หน่วยความจำเสมือน
ดังที่ @Daniel R Hicks ชี้ให้เห็นในคำตอบอื่น OSes ใช้หน่วยความจำเสมือน ความหมายคือแอปพลิเคชันไม่ทำงานกับที่อยู่หน่วยความจำจริง แต่เป็นแอปที่มีให้โดย OS
เทคนิคนี้ช่วยให้ระบบปฏิบัติการย้ายข้อมูลบางส่วนจาก RAM ไปยัง Pagefile (Windows) หรือ Swap (* NIX) ที่เรียกว่า HDD ช้ากว่า RAM เล็กน้อย แต่ก็ไม่ใช่ปัญหาร้ายแรงสำหรับข้อมูลที่เข้าถึงได้ยากและอนุญาตให้ระบบปฏิบัติการให้แอปพลิเคชัน RAM มากกว่าที่คุณติดตั้งจริง
เพจจิ้ง
สิ่งที่เรากำลังพูดถึงคือเรียกว่ารูปแบบการกำหนดแอดเดรสแบบแบน
การเพจคือโครงร่างการกำหนดแอดเดรสทางเลือกที่อนุญาตให้กำหนดแอดเดรสหน่วยความจำเพิ่มเติมที่ปกติคุณสามารถทำได้ด้วยหนึ่งคำศัพท์เครื่องในโมเดลแฟล็ต
ลองนึกภาพหนังสือที่เต็มไปด้วยคำ 4 ตัวอักษร สมมติว่ามี 1024 หมายเลขในแต่ละหน้า ในการพูดถึงตัวเลขคุณต้องรู้สองสิ่ง:
- จำนวนหน้าที่พิมพ์คำนั้น
- คำใดในหน้านั้นคือคำที่คุณกำลังค้นหา
นั่นคือวิธีที่ x86 ซีพียูสมัยใหม่จัดการกับหน่วยความจำ มันแบ่งออกเป็น 4 หน้า KiB (1024 คำต่อคำในเครื่อง) และหน้าเหล่านั้นมีตัวเลข (หน้าจริงๆแล้วอาจเป็น 4 MiB ใหญ่หรือ 2 MiB พร้อมPAE ) เมื่อคุณต้องการระบุเซลล์หน่วยความจำคุณต้องมีหมายเลขหน้าและที่อยู่ในหน้านั้น โปรดทราบว่าแต่ละเซลล์หน่วยความจำมีการอ้างอิงโดยตัวเลขหนึ่งคู่เท่านั้นซึ่งจะไม่เกิดกรณีสำหรับการแบ่งกลุ่ม
การแบ่งกลุ่ม
อันนี้ค่อนข้างคล้ายกับเพจ มันถูกใช้ใน Intel 8086 เพียงเพื่อตั้งชื่อตัวอย่างหนึ่ง กลุ่มที่อยู่ปัจจุบันเรียกว่าเซ็กเมนต์หน่วยความจำไม่ใช่หน้าเว็บ ความแตกต่างคือส่วนสามารถทับซ้อนกันและพวกเขาทับซ้อนกันมาก ตัวอย่างเช่นใน 8086 เซลล์หน่วยความจำส่วนใหญ่มีอยู่ใน 4096 เซกเมนต์ที่ต่างกัน
ตัวอย่าง:
สมมติว่าเรามีหน่วยความจำ 8 ไบต์ทั้งหมดถือศูนย์ยกเว้นไบต์ที่ 4 ซึ่งเท่ากับ 255
ภาพประกอบสำหรับโมเดลหน่วยความจำแบบแบน:
_____
| 0 |
| 0 |
| 0 |
| 255 |
| 0 |
| 0 |
| 0 |
| 0 |
-----
ภาพประกอบสำหรับหน่วยความจำเพจที่มีเพจขนาด 4 ไบต์:
PAGE0
_____
| 0 |
| 0 |
| 0 | PAGE1
| 255 | _____
----- | 0 |
| 0 |
| 0 |
| 0 |
-----
ภาพประกอบสำหรับหน่วยความจำที่แบ่งเป็นเซ็กเมนต์ที่มี 4 ไบต์แบ่งเป็น 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 |
----- ----- ----- -----
อย่างที่คุณเห็นไบต์ที่ 4 สามารถระบุได้สี่วิธี: (ที่อยู่จาก 0)
- ส่วนที่ 0 ชดเชย 3
- ส่วนงานที่ 1 ชดเชย 2
- ส่วนที่ 2 ชดเชย 1
- ส่วนที่ 3 ชดเชย 0
มันเป็นเซลล์หน่วยความจำเดียวกันเสมอ
ในเซ็กเมนต์การใช้งานจริงถูกเลื่อนมากกว่า 1 ไบต์ (สำหรับ 8086 เป็น 16 ไบต์)
สิ่งที่ไม่ดีเกี่ยวกับการแบ่งส่วนคือความซับซ้อน (แต่ฉันคิดว่าคุณรู้อยู่แล้ว) สิ่งที่ดีคือคุณสามารถใช้เทคนิคที่ชาญฉลาดเพื่อสร้างโปรแกรมแบบแยกส่วน
ตัวอย่างเช่นคุณสามารถโหลดโมดูลบางส่วนในเซกเมนต์จากนั้นเสแสร้งเซกเมนต์มีขนาดเล็กกว่าจริง ๆ (เพียงเล็กพอที่จะเก็บโมดูล) จากนั้นเลือกเซ็กเมนต์แรกที่ไม่ทับซ้อนกับโมดูลหลอกที่เล็กกว่าและโหลดโมดูลถัดไป และอื่น ๆ โดยทั่วไปสิ่งที่คุณจะได้รับด้วยวิธีนี้คือหน้าขนาดผันแปร