Някой ден е забавно да погледнем повърхностното ниво на компютърното преживяване, а в други дни е забавно да се ровим направо във вътрешните работи. Днес ние разглеждаме структурата на паметта на компютъра и колко неща можете да опаковате в памет на RAM.
Днешната сесия за въпроси и отговори ни идва с любезното съдействие на SuperUser - подразделение на Stack Exchange - обединяване на уеб сайтове с въпроси и отговори.
Reader на SuperUser Йохан Смохан се занимава с това как типът на процесора и размерът на паметта работят заедно, за да се получи общ брой адреси. Той пише:
Колко адреси за памет можем да получим с 32-битов процесор и 1GB овен и колко от него разполагат с 64-битов процесор?
Мисля, че е нещо подобно:
1GB от овен разделени или с 32 бита 4 бита (?), За да получите броя на адресите на паметта?
Прочетох на Wikipedia, че 1 адреса на паметта е 32 бита широк или 4 октета (1 октет = 8 бита) в сравнение с 64-битов процесор, където 1 адрес на паметта или 1 цяло число е 64 бита широк или 8 октета. Но не знам дали и аз го разбирах правилно.
Това са видовете въпроси, които могат да държат един любопитен скитник през нощта. Колко адреса са на разположение под всяка хипотетична система на Йохан?
Сътрудникът на SuperUser Gronostaj предлага известно разбиране как RAM се разделя и използва:
Кратък отговор: Броят на наличните адреси е равен на по-малките от тези:
- Размер на паметта в байтове
- Най-голямо неписано цяло число, което може да бъде запазено в машинната дума на процесора
Дълъг отговор и обяснение на горното:
Паметта се състои от байтове (B). Всеки байт се състои от 8 бита (b).
1 B = 8 б
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
Всеки байт памет има свой собствен адрес, без значение колко голяма е машинната дума на процесора. Напр. Intel 8086 CPU беше 16-битов и адресира паметта по байтове, така че и модерните 32-битови и 64-битови процесори. Това е причината за първото ограничение - не можете да имате повече адреси от байтове в паметта.
Адреса на паметта е само няколко байта, които процесорът трябва да прескочи от началото на паметта, за да стигне до онази, която търси.
- За достъп до първия байт той трябва да прескочи 0 байта, така че адресът на първия байт е 0.
- За достъп до втория байт трябва да пропусне 1 байт, така че неговият адрес е 1.
- (и така нататък… )
- За достъп до последния байт процесорът прескача 1073741823 байта, така че неговият адрес е 1073741823.
Сега трябва да знаете какво 32-битов всъщност означава. Както споменах по-рано, това е размерът на машинната дума.
Машината дума е размерът на паметта, която CPU използва за задържане на номера (в RAM, кеш или вътрешни регистри). 32-битовият CPU използва 32 бита (4 байта) за задържане на номера. Адресите на паметта също са цифри, така че на 32-битов CPU адресът на паметта се състои от 32 бита.
Сега помислете за това: ако имате един бит, можете да запазите две стойности върху него: 0 или 1. Добавете още един бит и имате четири стойности: 0, 1, 2, 3. На три бита можете да запазите осем стойности : 0, 1, 2 ... 6, 7. Това всъщност е двоична система и работи така:
Бинарен десетичен 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, а не десетичната
0000
, тогава добавяте 1 и получавате0001
, добавете още веднъж и вие имате0010
, Това, което се случи тук, е като с десетичен знак09
и добавяне на едно: променяте 9 към 0 и увеличавате следващата цифра.От горния пример можете да видите, че винаги има максимална стойност, която можете да запазите в брой с постоянен брой битове - защото, когато всички битове са 1 и се опитате да увеличите стойността с 1, всички битове ще станат 0, номер. Това се нарича "цялостно препълване" и причинява много неприятни проблеми както за потребителите, така и за разработчиците.
11111111 = 255 + 1 ----------- 100000000 = 0 (9 бита тук, така че 1 е подрязана)
- За 1 бит най-голямата стойност е 1,
- 2 бита - 3,
- 3 бита - 7,
- 4 бита - 15
Най-големият брой е винаги 2 ^ N-1, където N е броят на бита. Както казах по-рано, адресът на паметта е число и има максимална стойност. Ето защо размерът на машинната дума също е ограничение за броя на наличните адреси на паметта - понякога процесорът ви просто не може да обработва достатъчно големи числа, за да адресира повече памет.
Така че на 32 бита можете да запазите номера от 0 до 2 ^ 32-1, а това е 4 294 967 295. Това е повече от най-големия адрес в 1 ГБ RAM, така че в конкретния случай количеството RAM ще бъде ограничаващият фактор.
Ограничението на RAM за 32-битов процесор е теоретично 4 GB (2 ^ 32), а за 64-битов CPU е 16 EB (екзабайти, 1 EB = 2 ^ 30 GB). С други думи, 64-битовият процесор може да адресира целия интернет ... 200 пъти;) (изчислен от WolframAlpha).
Обаче в реални операционни системи 32-битовите процесори могат да адресират около 3 GiB от RAM. Това се дължи на вътрешната архитектура на операционната система - някои адреси са запазени за други цели. Можете да прочетете повече за така наречената бариера от 3 GB на Wikipedia. Можете да вдигнете тази граница с разширение за физически адреси.
Говорейки за адресирането на паметта, има няколко неща, които трябва да спомена:виртуална памет, сегментиранеипейджинг.
Виртуална памет
Както @Daniel R Hicks посочи в друг отговор, ОС използват виртуална памет. Това означава, че приложенията всъщност не работят с истински адреси на паметта, а тези, предоставени от операционната система.
Тази техника позволява на операционната система да премества някои данни от RAM в т.нар. Pagefile (Windows) или Swap (* NIX).HDD е малко по-малък от RAM, но това не е сериозен проблем за рядко достъпните данни и позволява на операционната система да предоставя повече приложения, отколкото сте инсталирали.
пейджинг
Това, за което говорехме досега, се нарича платена схема за адресиране.
Пейджинг е алтернативна схема за адресиране, която позволява да се адресира повече памет, която обикновено бихте могли да постигнете с една машинна дума в плосък модел.
Представете си книга, пълна с думи от 4 букви. Да приемем, че има 1024 номера на всяка страница. За да се обърнете към номер, трябва да знаете две неща:
- Броят на страницата, на която е отпечатана тази дума.
- Коя дума на тази страница е тази, която търсите.
Сега това е точно как модерните процесори x86 обработват паметта. Тя е разделена на 4 килобайта страници (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 | ----- ----- ----- -----
Както можете да видите, четвъртия байт може да бъде адресиран по четири начина: (адресиране от 0)
- Сегмент 0, отместване 3
- Сегмент 1, отместване 2
- Сегмент 2, отместване 1
- Сегмент 3, отместване 0
Винаги е една и съща клетка за памет.
При реализациите в реално време сегментите се изместваха с повече от 1 байт (за 8086 това беше 16 байта).
Какво е лошо за сегментацията е, че е сложно (но мисля, че вече знаете това;) Какво е добре, е, че можете да използвате някои умни техники за създаване на модулни програми.
Например, можете да заредите някой модул в сегмент, а след това да се преструвате, че сегментът е по-малък, отколкото е всъщност (достатъчно малък за задържане на модула), след това изберете първи сегмент, който не се припокрива с този псевдо-малък и зарежда следващия модул и т.н. По принцип това, което получавате по този начин, е страници с променлив размер.
Имате ли нещо, което да добавите към обяснението? Звучи в коментарите. Искате ли да прочетете повече отговори от други потребители на Stack Exchange? Вижте цялата тема на дискусията тук.