Эксперт Hardware
|
|
1 | |
Память компьютера21.10.2017, 01:59. Показов 35115. Ответов 23
Метки нет (Все метки)
..разбираюсь с памятью, и хотел-бы поделиться. в своих догадках вполне могу ошибаться, так-что поправкам буду только рад. Подсистема памяти - наиболее мутная и сложная часть архитектуры, и на мой взгляд программирование нужно начинать именно с неё. По настроению и времени - буду дополняться. (хотя что-бы охватить весь материал, наверное не хватит и всей жизни). ------------------------------------------- ПРОЦЕССОР. БЛОК УПРАВЛЕНИЯ ПАМЯТЬЮ Процессоры изначально заточены под сегментную организацию памяти, иначе зачем было вводить шесть сегментных регистров CS..FS. Более того, они не имеют механизмов запрещения сегментации, тогда-как страничную трансляцию можно включать\выключать битом(31-PAGE) регистра управления процессором(CR0). В аппаратной части подсистемы памяти фигурируют 3 типа адресов: логический, линейный и физический. Из этой троицы, ЦП оперирует только логическим адресом, который использует в своих программах программист. Для трансляции остальных адресов, процессор имеет блок управления памятью - MMU (Memory Management Unit). Логический адрес состоит из сегмента и смещения - CS:EIP, DS:ESI, ES:EDI, etc. MMU собирает эти составляющие, преобразуя лог\адрес в линейный (в диапазоне 0..N). Если в регистре(CR0) включён страничный режим, то в дело вступает транслятор страниц MMU. Если-же страничное преобразование выключено, то линейный адрес совпадает с физическим, который и выставляется процессором на внешнюю шину-адреса. Схематически это выглядит так (в сегментных регистрах лежит 2-байтный селектор сегмента, EA - смещение, тёмным выделены блоки MMU): На этом рисунке бит 'PAGE' в регистре(CR0) имеет значение нуль, т.е. страничная трансляция отключена и вся физическая память разбита только на сегменты. Линейный адрес совпадает с физическим. Если установить 'PAGE=1', то перемычка с транслятора страниц снимается, и на сегментную организацию накладывается страничная - блоки фиксированного размера по 4Кб, которые составляют виртуальную память. Только при использовании страничной трансляции доступны 36-битные физические адреса до 64-Гбайт (PSE, PAE). В сегментной модели, память представляется группой независимых блоков. Для адресации байта, программа использует логический адрес состоящий из селектора сегмента, и смещения. Селектор выбирает определённый сегмент, а смещение указывает на конкретный байт в пространстве выбранного сегмента: Селекторы хранятся в сегментных регистрах. При трансляции логического адреса в линейный, смещение выставляется на шину без модификации. Вся трансляция сводится к тому, чтобы найти в памяти базу указанного сегмента, и прибавить к ней смещение. Адрес базы хранится в дескрипторе сегмента. ДЕСКРИПТОР - БАЗА, ЛИМИТ, ЗАЩИТА В защищённом режиме размер сегментов может быть произвольным: от 1-байта до 4-Гбайт. Любому из них в отдельности можно задавать свои атрибуты(Access) и ограничивать доступ двойной защитой. От сюда и название режима - защищённый - Protected! Во-первых можно указать уровень привилегий (RPL), т.е. с какого из 4-х колец защиты(0-3) возможен доступ к сегменту. Во-вторых - какие можно проводить операции с его данными: чтение, запись, исполнение. Каждый сегмент памяти описывает его-собственный дескриптор. Размер дескриптора 8-байт (64-бита). В нём хранится линейный адрес начала сегмента в памяти (Base=32-бит), размер сегмента (Limit=20-бит), и атрибуты защиты (Access=12-бит). При обращении к сегменту, MMU сначала проверяет значение смещения, которое не должно превышать лимит. То есть адрес не должен выходить за пределы сегмента, в противном случае ЦП сгенерит исключение. Если с базой и атрибутами ситуация прозрачна, то к лимиту есть вопросы.. Например, как 20-ю битами определить размер сегмента в 4-Гб? Ответ - его размер указывается в единицах измерения! Среди атрибутов, в дескрипторе имеется т.н. бит гранулярности(G). Если он сброшен, то единицей измерения считается байт, если взведён - то 4-Кбайтная страница. Отсюда следует, что при G=0 размер\лимит сегмента ограничен значением 1.048.576 байт (20-бит = 1Мб), а при G=1 включается множитель(4Кб): 1048576*4096=4 Гбайт. ТАБЛИЦЫ ДЕСКРИПТОРОВ - GDT, LDT, IDT Обычно программа занимает несколько сегментов памяти: кода(CS), данных(DS), стека(SS). У каждого из них свой дескриптор. Итого - три., плюс три вспомогательных сегмента, на которые указывают ES\FS\GS. Внутри одной задачи (программы), все её дескрипторы собираются в Таблицу дескрипторов. Таких таблиц тоже всего три: -1. Глобальная таблица дескрипторов(GDT) - системная и может быть только одна. Доступна всем задачам, если не нарушаются права доступа. Обычно GDT включает дескрипторы сегментов кода и данных ОС, сегментов состояния задач(TSS). Под дескрипторную таблицу текущей задачи(LDT) выделяется отдельный сегмент. Дескриптор этого сегмента хранится в GDT. -2. Локальная таблица(LDT) для каждой задачи своя. Их кол-во определяется кол-вом активных задач в системе: LDT-1,2,3,,N. К локальным дескрипторам может обращаться только та задача, в таблице которой эти дескрипторы прописаны. В каждый момент времени процессору доступна только одна из локальных таблиц(LDT) - таблица текущей задачи. -3. Таблица прерываний(IDT) служит заменой таблицы векторов прерываний реального режима. Процессор обращается к ней при возникновении аппаратных исключений. Прямой доступ со стороны прикладной задачи к сегменту IDT не возможен, т.к. бит индикатора таблицы(TI) в селекторе сегмента позволяет выбирать только GDT или LDT. В этой таблице хранятся дескрипторы шлюзов-прерываний и ловушек, по аналогии с векторами реального режима. Все эти таблицы хранятся в памяти, а их физические адреса лежат в регистрах процессора GDTR, LDTR, IDTR соответственно. Команды записи [LGDT\LLDT\LIDT] в них являются привилегированными (запись возможна только с нулевого кольца), зато чтение в PMode никак не препятствуется процессором: SGDT\SLDT\SIDT. Кроме этих таблиц, в окружении задачи обязательно присутствует сегмент TSS (Task State Segment) - сегмент состояния задачи. При переключении задач, в этот сегмент сбрасывается полная инфа о текущей задаче - ccылка на предыдущую запись TSS (для восстановления приостановленной задачи), текущее состояние всех (кроме FPU) регистров ЦП, указатели на внутренний стек, битовая карта прерываний, и пр. Описание сегмента(TSS) можно найти здесь: http://www.club155.ru/x86addr-tss, или в манах Intel'a Vol.3. Селектор дескриптора(TSS) хранится в регистре(TR) процессора - Task Register. Нужно отметить, что кроме дескрипторов 'своих' сегментов, в локальной таблице(LDR) присутствуют и сегменты ОС. То есть в пространстве памяти есть общие для всех сегменты. Это касается импортируемых API-функций системы. Эти функции лежат в сегментах памяти ОСи, к которым нет прямого доступа из прикладного уровня. Поэтому ОС (в зависимости от импорта) дополняет LDT текущей задачи, некоторыми дескрипторами из своей\глобальной таблицы. Такой подход исключает переключение задач при вызове API. Прикладной задаче разрешено читать только те сегменты ОСи, которые она прописала в её локальную таблицу дескрипторов(LDT).
7
|
21.10.2017, 01:59 | |
Ответы с готовыми решениями:
23
Обсуждение статьи "Память компьютера" Память компьютера. (Сегмент, смещение и т.д.) Почему в TASM нельзя сравнивать память-память? Память компьютера Уменьшилась память компьютера |
Эксперт Hardware
|
|
21.10.2017, 02:06 [ТС] | 2 |
СЕГМЕНТНЫЕ РЕГИСТРЫ. СЕЛЕКТОР
В защищённом режиме, основной функцией сегментных регистров является определение местоположения дескрипторов. Начиная с процесоров i286 размер регистров CS..FS не 2, а 10-байт. Из них программно доступны только старшие 2-байта, в которых хранится т.н. Селектор дескриптора. Селектор - это номер дескриптора в таблице (GDT\LDT). Получается цепочка - селектор указывает на дескриптор, а дескриптор описывает физический сегмент памяти. Младшие 8-байт сегментного регистра программно недоступны - затенены. В них на аппаратном уровне копируется весь 8-байтный дескриптор, на который указывает данный селектор. Один раз скопировав дескриптор в сегментный регистр, MMU (в течении одной задачи) больше не обращается к таблице дескрипторов вообще. В манах интела можно найти состояние упомянутых регистров при включении машины. Хоть это и реальный режим, зато отчётливо видны в сегментных регистрах: 2-байтный\видимый селектор, и скрытая\8-байтная часть - база, размер и атрибуты, т.е. те-же поля, что и в дескрипторах. Заслуживают внимания и стартовые значения регистровой пары CS:EIP, которая при таких значениях передаёт управление по логическому адресу F000:FFF0h (линейный адрес FFFF0h), где находится первая инструкция кода BIOS: Селектор - это часть логического адреса. Посмотрим на описание его полей: Код
15-----------------3 2 1-0 __________________ ____ _____ | Индекс | TI | RPL | |__________________|____|_____| Биты(0-1) = 2-бита для уровня RPL - Requested Privilege Level (4 кольца защиты); Бит(2) = 1-бит выбора таблицы - GDT или LDT; Биты(3-15) = 13-бит для номера дескриптора в таблице. Когда MMU транслирует логический адрес он, проверив в селекторе биты(TI-RPL), обнуляет их. Сброс трёх-младших битов селектора приводит к тому, что индекс всегда получается кратным восьми, - а это как раз размер одного дескриптора. В результате - индекс превращается в адрес в таблице(LDT). Нулевой дескриптор в таблицах не используется и должен быть забит нулями: Код
| Kernel (RPL=0) || User (RPL=3) | Регистры | селектор (bin) || селектор (bin) | Регистры ---------|---------------------||---------------------|--------- CS=08h - 0000000000001.0.00 || 0000000000011.0.11 - CS=1Bh DS=10h - 0000000000010.0.00 || 0000000000100.0.11 - DS=23h SS=18h - 0000000000011.0.00 || 0000000000101.0.11 - SS=2Bh ES=20h - 0000000000100.0.00 || 0000000000110.0.11 - ES=33h FS=28h - 0000000000101.0.00 || 0000000000111.0.11 - FS=3Bh GS=30h - 0000000000110.0.00 || 0000000001000.0.11 - GS=43h Селекторы остальных сегментных регистров будут увеличиваться в таблице на 8 (размер одного дескриптора). В этом легко убедиться, если открыть любую программу в отладчике OllyDbg, и посмотреть на их значения (в сл.полях лежат база с лимитом - скрытая часть регистра): Код
ES 0023 32bit 0(FFFFFFFF) CS 001B 32bit 0(FFFFFFFF) SS 0023 32bit 0(FFFFFFFF) DS 0023 32bit 0(FFFFFFFF) FS 003B 32bit 7FFDF000(FFF) GS 0000 NULL EDX 7C90E4F4 ntdll.KiFastSystemCallRet EBX 7FFD9000 ESP 0006FFC4 EBP 0006FFF0 EDI 7C910208 ntdll.7C910208 EIP 00403000 002.
7
|
Эксперт Hardware
|
|
28.10.2017, 11:09 [ТС] | 3 |
Сообщение было отмечено Mikl___ как решение
Решение
SYSER KERNEL DEBUGGER
Все, кто имел дело с легендарным отладчиком SoftIce знают насколько мощный это инструмент. Только вот проблема - он не дружит с платформами WinХР+. Вернее нужно добавлять левые патчи и не факт, что после этого мы увидим долгожданное окно отладчика. Автор перепробовал много советов из сети, но так и не добился результата. Этих недостатков лишён "SYSER" - китайский клон Айса, о котором хотелось-бы сказать пару слов. Установка проходит в штатном режиме без эксцессов. Отладчик имеет резидентные (невыгружаемые) модули, поэтому нужна перезагрузка, после которой можно в любой момент вызвать его комбинацией [Ctrl+F12] и исследовать ядро прямо из под винды. Мастдай при этом получает глухой завис, пока не выйдешь из отладки. Консоль имеет мощную справку, причём для каждой команды в отдельности и с примерами. Ведение логов со-сбросом их в файл. Юсбишная мыша в окне не работает, - только PS\2. ---------------------------- В реальном режиме, под систему выделяются младшие адреса памяти. В винде наоборот - старшая половина. Если проц 32-битный, то и шина-адреса у него 32-бит с макс.адресом 0xFFFFFFFF (4Гб). Система выделяет для юзера область в диапазоне 00010000-7FFFFFFFh, а сама занимает адреса 80000000h и выше. Юзерскую кучу с двух сторон подпирают два спец\буфера по 64Кб для вылавливания некорректных указателей. Обращения к этим областям из юзер-моды расценивается виндой как нарушение периметра неприятелем и жёстко пресекаются. Поэтому пользовательское пространство начинается с адреса 0х00010000, а не ноль. (напомню, что это виртуальные VA-адреса, и физ\памяти может столько не быть): Код
|<------ User memory ------->| |<----- Kernel memory ---->| | | | | |FFFFh|----------------------------|FFFFh|--------------------------| |-----+-----> 64к + 64к <------+-----+ | | | | |<--0x00000000h 0x80000000 0xFFFFFFFF-->| После запуска 'клон-Айса', в его консоли сразу появляется инфа о кол-ве процедур экспортируемых каждой из системных библиотек, кол-ве найденых в системе API (2791), и названия файла ядра - 'ntoskrnl.exe' - кернел оси NT. Одной из основных назначений ядерных отладчиков является перехват системных ошибок (всплытие по ошибке), чтобы админ смог локализовать и исправить её. Самый коварный из ошибок - это BSOD, захлопывающий перед админом все двери. Его обрабатывает API "KeBugCheckEx", адрес которой и показывает Syser. Если быть точным, то лог показывает не кол-во экспортируемых функций (например для 'Kernel32.dll' указано 937), а кол-во символьных таблиц (Symbols), что по сути одно и то-же. Таблицы символов содержат имена API-функций и переменных в конкретном файле. Они генерируются линкером, но не включаются в экзешник, поскольку для выполнении кода эта инфа не нужна - линкер превращает имена в их адреса. Как видим Syser хорошо вооружён, и способен распознать приличное кол-во имён API-функций. Таблицу символов Syser хранит в файле 'mfcsym.txt' размером ~1Mb: Код
Syser : Version 1.99.1900.1217 Build 04/27/2011 Syser : Load module 937 export symbols C:\WINDOWS\system32\Kernel32.dll Syser : Load module 596 export symbols C:\WINDOWS\system32\GDI32.dll Syser : Load module 720 export symbols C:\WINDOWS\system32\User32.dll Syser : Load module 648 export symbols C:\WINDOWS\system32\AdvApi32.dll Syser : Load module 114 export symbols C:\WINDOWS\system32\ws2_32.dll Syser : Load module 815 export symbols C:\WINDOWS\system32\msvcrt.dll Syser : Load module 28 export symbols C:\WINDOWS\system32\comdlg32.dll Syser : Load module 169 export symbols C:\WINDOWS\system32\comctl32.dll Syser : Load module 109 export symbols C:\WINDOWS\system32\ImageHlp.dll Syser : Load module 221 export symbols C:\WINDOWS\system32\win32k.sys Syser : Load module 1016 export symbols C:\WINDOWS\system32\ntdll.dll Syser : Load module 92 export symbols C:\WINDOWS\system32\hal.dll Syser : Load module 1461 export symbols C:\WINDOWS\system32\ntoskrnl.exe Syser : Load API 2791 records Syser : Windows kernel name 'ntoskrnl.exe' Base = 804d7000 Syser : Patch KeBugCheckEx = 805337EB Syser : You can press "CTRL+F12" to active Syser ! > Регистры процессора Теперь, из окна отладчика перейдём на консоль(Ctrl+2), и посмотрим на регистры.. Поскольку речь идёт о памяти, нам интересны только адреса. А это значения селекторов в сегментных регистрах, флаги в CR(0..4), и базы расположения дескрипторных таблиц(GDT..LDT). Регистры(РОН) я исключил из этого списка. Здесь видно, что в отладчик загружена программа прикладного уровня (CS=1Bh, а не 08h), данные и стек делят один сегмент, зато селектор(FS=3Bh). Его дескриптор указывает на первый SEH-фрейм, где хранится цепочка обработчиков исключений Win. Эта область находится за макушкой текущего стека. SEH (Structured Exception Handling) - это отдельная тема, и позже мы ознакомимся с общими принципами работы этого механизма. Отладочные (Debug) регистры - это вообще жесть! Доступ к ним возможен только с Ring(0), или в реальном режиме. Непросвящённым, советую ознакомиться с этими регистрами по ближе. Они служат для описания характера точек останова (BreakPoint). Битовые маски позволяют ставить BP отдельно на: операции с памятью (R\W\Exec), программные\аппартные прерывания, и обращения к портам ввода-вывода. При помощи бряков на I\O можно написать полноценный эмулятор на любое из внешних устройств. В регистрах управления процессором (Control) зашита инфа об организации памяти и кэша. По сути, эти биты вкл\откл отдельные блоки ЦП, в том числе и трансляторы адресов в MMU. Бит(РЕ) в регистре(CR0) от слова 'PageEnable' - включает транслятор страниц (виртуальную память). В регистре(CR3) хранится линейный адрес начала таблицы PDT - PageDirectoryTable - таблица каталога страниц виртуальной памяти. В битах регистра(CR4): PSE = 4-Мбайтные страницы (иначе 4-Кбайт), PAE = 36-битный адрес (иначе 32), и т.д.. Ну и последними в списке регистров находятся данные о расположение в памяти дескрипторных таблиц (регистры GDTR..LDTR). Из отчёта видно, что их базы находятся в системной области памяти (выше 0х80000000), причём лимиты (размеры) у каждой из таблиц разные. Если у вас многоядерный ЦП, то в команде консоли нужно указать номер ядра: Код
>> cpu 0 Segment Register CS=0x001B, DS=0x0023, ES=0x0023, FS=0x003B, GS=0x0000, SS=0x0023 Debug Register DR0=0x00000000, DR1=0x00000000, DR2=0x00000000, DR3=0x00000000 DR6=0xFFFF0FF0, DR7=0x00000400 Control Register CR0=0x80010031, CR2=0x7C86495C, CR3=0x17CEF000, CR4=0x000006D9 CR0: PE=1 MP=0 EM=0 TS=0 ET=1 NE=1 WP=1 AM=0 CD=0 PG=1 CR3: PWT=0 PCD=0 Page-Directory Base = 17CEF000 CR4: VEM=1 PVI=0 TSD=0 DE=1 PSE=1 PAE=0 MCE=1 PGE=1 PCE=0 OSFXSR=1 OSXMMEXCPT=1 GDT Base=8003F000 Limit=03FF IDT Base=8003F400 Limit=07FF TSS Selector=0028 Base=80042000 Limit=20AB LDT Selector=0000 Base=00000000 Limit=FF394D44 Дескрипторные таблицы GDT\LDT Содержимое дескрипторных таблиц таит в себе много тайн и загадок, которые 'Syser' решает в два-счёта. Введём с консоли их имена и посмотрим на реакцию отладчика. Упс - нет таблицы(LDT). Значит все сегменты моей программы описывают дескрипторы глобальной таблицы(GDT), и LDT для прикладной задачи не так важна. Зато GDT забита дескрипторами под-завязку. Я не стал выкладывать сюда всю портянку, а ограничился лишь наиболее информативными из них. В логе указываются номера селекторов в сегментных регистрах, тип дескриптора в таблице, и его содержимое - линейный адрес базы сегмента в памяти, его размер и атрибуты. DPL (Descriptor Privelege Level) - определяет, кто хозяин дескриптора (Ring): 0=ядро, 1=драйвер, 2=сис\библиотеки, 3=юзер. NP (NoPresent) = сегмент не активен. Атрибут(E) = 'Exec' исполнение (выставляется только в сегментах кода), (А) = 'Accessed' устанавливается при любом обращении к сегменту, чтобы выявлять сегменты, к которым меньше всего было обращений (например, раз в 10-сек). При ограниченном кол-ве физ\памяти, система сбрасывает сегменты без бита(А) в своп на диск. Вообще-то, среди атрибутов дескриптора сегмента должен быть ещё и бит(E) - 'Expand Down', который определяет направление роста адресов в сегменте, но почему-то 'Syser' его не отображает. Этот бит применяется только к сегментам данных. Поскольку между сегментами данных и стека нет особой разницы кроме-как направление роста адреса (неисполняемый стек), то выставленный бит(E) в сегменте данных определял сегмент стека, где сл.адрес уменьшается, а не увеличивается. Напомню про базовые адреса сегментов.. Если старший байт базы равен(0x7F) и ниже, то сегмент юзерский, если (0x80) и выше - то им заправляет система. Сам сегмент(GDT) занимает в памяти 1-Кбайт (3FFh), и лежит в младших адресах системы 0x8003F000. Если размер одного дескриптора 8-байт, то выходит, что в данной таблице имеется место под 1024/8=128 дескриптора, хотя сам сегмент(GDT) может расширятся динамически и 128-дескрипторов в нём - это не предел.<P> По содержимому GDT можно определить, сколько прикладных задач запущено в системе. Поскольку каждая из задач имеет свой TSS - Task State Segment, то достаточно посчитать кол-во их дескрипторов - здесь 4 штуки с селекторами 28,50,58,A0. И точно.. на тот момент у меня были запущены: Тотал, Опера, AkelPad и сам отладчик 'Syser'. На отладчик я переключился из AkelPad'a, а система сразу сбросила контекст Akela'a в его сегмент(TSS), и выставила в текущем TSS отладчика атрибут(В), т.е. 'Busy' - занятый. Процессор не поддерживает рекурсию задач (вызов самой-себя), для чего и используется этот бит(Busy): Код
>> ldt No LDT ---------- >> gdt GDTBase = 8003F000 Limit = 3FF ---------------------------------------------------- Sel. Type Base Limit DPL Attributes 0000 Reserved 00000000 00000000 0 NP 0008 Code32 00000000 FFFFFFFF 0 P RE A 0010 Data32 00000000 FFFFFFFF 0 P RW A 001B Code32 00000000 FFFFFFFF 3 P RE A 0023 Data32 00000000 FFFFFFFF 3 P RW A 0028 TSS32 80042000 000020AB 0 P B 0030 Data32 FFDFF000 00001FFF 0 P RW A 003B Data32 7FFDF000 00000FFF 3 P RW A 0043 Data16 00000400 0000FFFF 3 P RW 0048 Reserved 00000000 00000000 0 NP 0050 TSS32 80551380 00000068 0 P 0058 TSS32 805513E8 00000068 0 P 0060 Data16 00022F40 0000FFFF 0 P RW A 0068 Data16 000B8000 00003FFF 0 P RW 0070 Data16 FFFF7000 000003FF 0 P RW 0078 Code16 80400000 0000FFFF 0 P RE 0080 Data16 80400000 0000FFFF 0 P RW 0088 Data16 00000000 00000000 0 P RW 0090 Reserved 00000000 00000000 0 NP 0098 Reserved 00000000 00000000 0 NP 00A0 TSS32 82BC4358 00000068 0 P 00A8 Reserved 00000000 00000000 0 NP ........... 00D8 Reserved 00000000 00000000 0 NP 00E0 Code16 F7708000 0000FFFF 0 P RE C A 00E8 Data16 00000000 0000FFFF 0 P RW 00F0 Code16 804D8B28 00037CA7 0 P EO 00F8 Data16 00000000 0000FFFF 0 P RW 0100 Data32 F7718000 0000FFFF 0 P RW A 0108 Data32 F7718000 0000FFFF 0 P RW A 0110 Data32 F7718000 0000FFFF 0 P RW A 0118 Reserved 00008003 0000F120 0 NP ........... 03F8 Reserved 00000000 00000000 0 NP
7
|
Эксперт Hardware
|
|
28.10.2017, 11:11 [ТС] | 4 |
IDT - Interrupt Dispatch Table (диспетчеризация прерываний)
Как и GDT - эта таблица общая для всех задач, и система выделяет для них отдельные сегменты. Обращение к IDT возможно только на аппаратном уровне при возникновении исключений или аппаратных инт'ов. В таблице расписаны номера всех прерываний, которые в P-Mode называют дескрипторами шлюзов. Имеется всего три типа этих шлюзов: шлюз-прерывания 'Int' (точка входа в обработчик прерывания), шлюз-ловушки 'Trap' (адрес обработчиков исключений, как-правило SEH), и шлюз-задачи 'Task' (адреса TSS для переключения задач). Для наглядности, я рассортировал их здесь по содержимому и уровням привелегий(DPL). В таблице всего 256 записей с макс.номером(FFh). Для каждого INT выделены свои дескрипторы. Между шлюзами прерываний и ловушек много общего, поэтому 'Syser' их не разделяет, хотя шлюз-задачи удостоился от отладчика личной метки (Task). При генерации прерывания происходит следующее.. 1. Из регистра(IDTR) извлекается база таблицы(IDT), в которой по номеру INT определяется дескриптор этого прерывания. 2. Если бит(Р) - 'Present' - в найденном дескрипторе сброшен, значит данное прерывание не обрабатывается системой. В этом случае генерится исключение общей защиты. 3. Если бит(Р=1), то проверяется уровень привилегий (RPL) задачи, запросившей прерывание. RPL должен быть меньше\равно DPL дескриптора прерывания, иначе - опять ошибка. (для исключений и аппаратных прерываний этот пункт игнорируется). 4. Если правила не нарушаются, то происходит переключение стека и в стеке обработчика сохраняется указатель на стек прерванной задачи (SS:ESP). В стек помещаются регистры EFLAGS и CS:EIP. Для некоторых исключений последним в стек помещается ещё и код-ошибки. 5. После обработки прерывания, обработчик должен вытолкнуть из стека код-ошибки (если он там есть), и выполнить инструкцию IRETD, которая восстановит стек и вернёт управление прикладной задаче: Код
>> idt IDTBase = 8003F400 Limit = 7FF ----------------------------------------------------------------- Int Type Sel : Offset Attributes Module 0000 IntG32 0008:804DF360 DPL=0 P ntoskrnl 000E IntG32 0008:F200A5C0(0008:804E167E) DPL=0 P Syser(ntoskrnl) 0013 IntG32 0008:804E1CAC(0008:804E18F3) DPL=0 P ntoskrnl(ntoskrnl) 001F IntG32 0008:80712FD0(0008:804E18F3) DPL=0 P hal(ntoskrnl) 00FF IntG32 0008:804DE4D0 DPL=0 P ntoskrnl 0002 TaskG 0058:0000113E(0008:804DF5C6) DPL=0 P (ntoskrnl) 0008 TaskG 0050:00001198(0008:804E06AD) DPL=0 P (ntoskrnl) 0012 TaskG 00A0:804E18F3 DPL=0 P ntoskrnl 0001 IntG32 0008:804DF4DB DPL=3 P ntoskrnl 0003 IntG32 0008:804DF8AD DPL=3 P ntoskrnl 0004 IntG32 0008:804DFA30 DPL=3 P ntoskrnl 002A IntG32 0008:804DEBA2 DPL=3 P ntoskrnl 002B IntG32 0008:804DECA5 DPL=3 P ntoskrnl 002C IntG32 0008:804DEE44 DPL=3 P ntoskrnl 002D IntG32 0008:F7ABCF96(0008:804DF78C) DPL=3 P SDbgMsg(ntoskrnl) 002E IntG32 0008:804DE631 DPL=3 P ntoskrnl 002C IntG32 0008:804DEE44 DPL=3 P ntoskrnl 002D IntG32 0008:F7ABCF96(0008:804DF78C) DPL=3 P SDbgMsg(ntoskrnl) 0020 Reserved 0008:00000000 DPL=0 NP .......... 0029 Reserved 0008:00000000 DPL=0 NP 00FC IntG32 0008:804DE4BB DPL=0 P ntoskrnl 00FD IntG32 0008:80713464(0008:804DE4C2) DPL=0 P hal(ntoskrnl) 00FE IntG32 0008:80713604(0008:804DE4C9) DPL=0 P hal(ntoskrnl) 00FF IntG32 0008:804DE4D0 DPL=0 P ntoskrnl
7
|
Эксперт Hardware
|
|
28.10.2017, 11:18 [ТС] | 5 |
Сегмент состояния задачи TSS
В заключении посмотрим, какой контекст сбрасывается в сегмент(TSS) при переключении задач, для её возобновления с того-же места. Указывающий на дескриптор(TSS) селектор, хранится в регистре(TR) процессора - 'Task Register'. Дескрипторы(TSS) каждой из запущенных задач должны быть прописаны в GDT (см.структуру GDT выше), причём в одном из них выставляется бит(В) - 'Busy' - занятый. Это дескриптор(TSS) активной задачи. Сегмент(TSS) содержит динамические и статические поля. К динамическим относятся поля для хранения РОН и адрес дескриптора(TSS) той задачи, с которой было переключение - 'Previous Task Link'. ЦП обновляет динамические поля при сохранении контекста задачи, во время переключения на другую задачу. К статическим полям относятся все\остальные: селектор(LDT), регистр(CR3) содержайщий адрес каталога страниц, указатели системных стеков SS:ESP(0,1,2), и базовый адрес карты разрешения ввода-вывода (I\O Permission Map Base Address). Статические поля заполняются системой при запуске задачи (создании TSS) и не меняются при переключении задач. Для управления вводом-выводом и прерываниями, в TSS имеются два бит-мапа. 'I\O Permission Map' используется при работе юзера с портами, т.е. когда IOPL меньше CPL (инструкции in\out). Если в этой карте бит соответствующий запрашиваемому порту равен(0), операция ввода-вывода проходит успешно, в противном случае генерится нарушение общей защиты. Таким образом получается двойная защита - привелегия(IOPL) и битовая карта разрешения в\в. Отсутсвие этой карты расценивается как запрет на ввод-вывод из Ring(3). Она введена только для прикладных задач. Вторая карта - это карта перенаправления прерываний - 'INT redirection bit-map'. Она имеет размер 32-байта, что позволяет перенаправлять: 32 * 8 (бит) = 256 пользовательских прерываний. Каждый бит в этом битмапе соответствует одному прерыванию, который отображается на соответствующий дескриптор в таблице(IDT). Если бит прерывания(INT) в битмапе взведён, то управление передаётся через дескриптор(IDT) обработчику защищённого режима. Когда бит сброшен, ЦП переназначает программное прерывание на таблицу векторов прерываний х8086, которая расположена по линейному адресу(0) юзерского пространства. Этот битмап используется в режиме V86 процессора: Код
>> tss TR = 0028 BASE = 80042000 LIMIT = 20AB LDT=0000 GS=0855 FS=5501 DS=0F56 SS=8B24 CS=8510 ES=EC8B EAX=1875FFEC EBX=FFFF02E8 ECX=FF1475FF EDX=55FF8B00 EIP=001CC2C9 ESI=14C25DFF EDI=55FF8B00 EBP=FFFF02E8 ESP=0875FF00 EFL=8B55FF8B CR3 = 17CEF000 SS0 = 0010:F5D58DE0 SS1 = 4338:D0685000 SS2 = C483:FFFF33B5 I/O permission map.....: BASE = 20AC, SIZE = 0 INT redirection bit-map: BASE = 80042068, SIZE = 32 0 1 2 3 4 5 6 7 - 8 9 A B C D E F ------------------------------------ 0x80042068 0400 0 0 1 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0x8004206A 0018 0 0 0 0 0 0 0 0 - 0 0 0 1 1 0 0 0 1 0x8004206C 1800 0 0 0 1 1 0 0 0 - 0 0 0 0 0 0 0 0 2 0x8004206E 0000 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 3 0x80042070 0000 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 4 0x80042072 0000 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 5 0x80042074 0000 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 6 0x80042076 0000 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 7 0x80042078 0000 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 8 0x8004207A 0000 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 9 0x8004207C 0000 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 A 0x8004207E 0000 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 B 0x80042080 0000 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 C 0x80042082 0000 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 D 0x80042084 0000 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 E 0x80042086 0000 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 F
7
|
Эксперт Hardware
|
|
30.10.2017, 18:34 [ТС] | 6 |
Сообщение было отмечено Mikl___ как решение
Решение
СТРАНИЧНАЯ ОРГАНИЗАЦИЯ ПАМЯТИ
Пришло время разобраться с виртуальной памятью, в основе которой лежит разбиение сегментов на страницы фиксированного размера по 4-Кб. Все линейки NT работают в 'гибридном режиме', когда на сегментную модель накладывается страничная. Такой подход предоставляет диспетчеру памяти полную свободу, и он может более тонко управлять общим пространством, перемещая блоки памяти с-места-на-место. Как-правило, размеры сегментов больше, чем размеры страниц, и ОС имеет отдельные аллокаторы памяти для каждого из слоёв: Global\Virtual\Heap-Alloc. Аппаратная поддержка страничной организации Страничная трансляция включается страшим битом(PG) регистра CR0. На вход транслятора страниц приходит линейный адрес (см.первый пост), который MMU разбивает на 3 части: старшие 10-бит выделяются под каталог страниц (10-бит = 1024 записи), средние 10-бит под таблицу страниц (одна из 1024 страниц), и младшие 12-бит выбирают смещение в странице физической памяти. Страницу физ\памяти называют Physical Frame - страничный кадр, или просто фрейм. Таким образом адресуется глобальное пространство: 1024*1024*4096=4Гб. Линейный адрес базы каталога-страниц в памяти, определяется содержимым регистра(CR3) 'PDBR - Page Directory Base Register': У каждой задачи свой каталог-страниц. Он создаётся при построении задачи виндовым загрузчиком. Загрузчик берёт весь бинарный образ программы на диске, и логически разбивает его на 4-Кбайтные страницы. Каждая из страниц нумеруется и отображается в виртуальную таблицу-страниц 'PT - PageTable'. Важно понять, что страницы не копируются с диска в таблицу, а именно отображаются в неё записями. Физическая память - разделяемый\дефицитный ресурс, и чтобы страницы не валялись без дела в памяти, нужные из них загружаются только по-требованию, а остальные ждут своей очереди на диске. Такой подход позволяет экономить физ\память, которой и так всегда не хватает. Каждую запись в таблице-страниц называют 'PTE - PageTableEntry'. Не трудно догадаться, что в PTE хранятся базы каждой из страниц. Размер одной записи\Entry равен 4-байта (32-бит), 20 из которых выделяют непосредственно под базу, а раз-уж остаются ещё 12-бит, то разумно использовать их под атрибуты страницы. (запись 'Entry' можно сравнить с дескриптором сегмента - тоже содержимое и пр.., только называются они по другому, хотя инфо-нагрузка та-же). Для случая, когда образ программы на диске слишком большой, и общее кол-во 4-Кбайтных виртуальных страниц уже вываливаются за края одной таблицы-страниц (всего 1024 записи), имеется т.н. каталог-страниц 'PD - PageDirectory'. В этом каталоге создаётся ещё одна запись 'PDE - PageDirectoryEntry', и в памяти выстраивается вторая таблица-страниц(PT-2) для этой-же задачи. Соответственно выбор конкретной записи в каталоге-страниц напрямую зависит от 10-ти старших бит линейного адреса. В большинстве случаях каталог-страниц содержит всего одну запись, с базой текущей таблицы-страниц, и ОС обходится малой кровью. Как и в таблице-страниц, в каталоге имеется место под 1024 записи. Ниже представлен формат 4-байтных записей(Entry) каталога и таблицы-страниц. Как видим, в них много общего за исключением того, что в поле 'Base' таблицы-страниц указывается физический адрес фрейма в памяти, а в каталоге - линейная база страничной таблицы: Манипуляции с мелкими блоками памяти в виде 4-Кбайтных страниц имеет свои преимущества - уменьшается фрагментация памяти, перемещение блоков происходит быстрее и пр. Но для больших объёмов данных волшебная палочка превращается в костыль. Каждое обращение проходит через несколько инстанций от каталога до физической памяти, а это\всё - время.. Учитывая современные объёмы данных, в системах NT+ размеры страниц увеличили до 4-Мбайт. Менеджер памяти может налету переключать размеры страниц, для чего имеется бит 'PSE - Extended Page Size' в регистре процессора(CR4). Трансляция линейного адреса в этом режиме происходит описанным выше способом, только исключается таблица-страниц, а её роль берёт на себя каталог. В результате, под смещение выделяется уже не 12, а 22-бита: Посмотрим, какое мнение имеет на этот счёт наши 'глаза и руки' - Syser. Инфу об организации страничной памяти можно выжать из него камандой 'PAGE'. Только сначала вскормим ему любую тестовую программу, посмотрим на общее кол-во процессов в системе, и на их расположение в памяти - 'ADDR' (системные и юзерские процессы я разделил пробелом): Код
>addr Process ID CR3 EPROCESS Process Name ----------------------------------------------------- PID = 0x0000 CR3 = 0x00039000 00000000 [System Idle Process] PID = 0x0004 CR3 = 0x00039000 82BCB830 [System] PID = 0x0178 CR3 = 0x04EEF000 829CC020 [smss] PID = 0x01B0 CR3 = 0x06F37000 82985B98 [csrss] PID = 0x01C8 CR3 = 0x07F3D000 82962DA0 [winlogon] PID = 0x01F4 CR3 = 0x0897B000 82972398 [services] PID = 0x0200 CR3 = 0x08A8D000 82936340 [lsass] PID = 0x0294 CR3 = 0x096D0000 829205B8 [svchost] PID = 0x02E8 CR3 = 0x09DF8000 828F47C8 [svchost] PID = 0x0314 CR3 = 0x0A2FE000 828E49F8 [svchost] PID = 0x037C CR3 = 0x0A994000 82869620 [svchost] PID = 0x03D8 CR3 = 0x0BAA9000 82842CA8 [svchost] PID = 0x0534 CR3 = 0x0E605000 827FF6C0 [explorer] PID = 0x05B0 CR3 = 0x0FD89000 827F4020 [ctfmon] PID = 0x0564 CR3 = 0x10B0E000 82527020 [SyserApp] PID = 0x0420 CR3 = 0x0C0EF000 82838DA0 [RaRegistry] PID = 0x05C8 CR3 = 0x10450000 827D4780 [RaUI] PID = 0x049C CR3 = 0x0758D000 824EE850 [AkelPad] PID = 0x05B8 CR3 = 0x10111000 827D9B90 [AlfaClock] PID = 0x05D0 CR3 = 0x10463000 827D4280 [punto] PID = 0x06EC CR3 = 0x1385E000 827EE4E8 [Totalcmd] PID = 0x0710 CR3 = 0x14FBD000 8286F7A8 [Opera] PID = 0x0684 CR3 = 0x0578B000 81FBB800 [CyberProg] //--- мой процесс 23 Process(s) Код
>> page Page Directory Physical 0578B000 Physical Attributes Linear Address Range ---------------------------------------------------- 05794000 P A U RW 00000000 - 003FFFFF 05792000 P A U RW 00400000 - 007FFFFF 1034B000 P A U RW 77C00000 - 77FFFFFF +--> UserPage (U) 08524000 P A U RW 7C800000 - 7CBFFFFF | 14D33000 P A U RW 7F400000 - 7F7FFFFF | 05790000 P A U RW 7FC00000 - 7FFFFFFF --+ 0003B000 P A S RW 80000000 - 803FFFFF 00400000 P G D A S RW 4M 80400000 - 807FFFFF 0003E000 P A S RW 80800000 - 80BFFFFF 0003C000 P A S RW 80C00000 - 80FFFFFF 01000000 P G D A S RW 4M 81000000 - 813FFFFF 01400000 P G D A S RW 4M 81400000 - 817FFFFF +--> SupervisorPage (S) 01800000 P G D A S RW 4M 81800000 - 81BFFFFF | 01C00000 P G D A S RW 4M 81C00000 - 81FFFFFF | 02000000 P G D A S RW 4M 82000000 - 823FFFFF | 02400000 P G D A S RW 4M 82400000 - 827FFFFF | 02800000 P G D A S RW 4M 82800000 - 82BFFFFF | 02C07000 P A S RW 82C00000 - 82FFFFFF | ...... | 01052000 P A S RW FF800000 - FFBFFFFF | 0003A000 P A S RW FFC00000 - FFFFFFFF --+ totals (467) U\S = страница юзера или супервизора системы; A = Accessed - к странице был доступ; P = Present - страница присутствует в памяти (может быть на диске); G = Global - глобальная страница; D = Dirty - грязная\изменённая страница, при выгрузке из памяти её нужно перезаписывать на диск. если страница чистая, то перезапись не требуется. Первая страница моего процесса легла по виртуальному адресу ноль и распласталась до адреса 0x003FFFFF, а это в аккурат 4Мб. Напомню, что это пользовательское пространство, поскольку лежит в диапазоне 0х7FFFFFFF. Все страницы вплотную прижаты друг-к-другу, и на лицо - выравнивание линейных баз на 4-Мбайтную границу (20-младших бит равны нулю). Следующие\все страницы так-же 4-Мбайтные, значит ОС использует 4-Кбайтные страницы только при выгрузки их из кэша, во-внешнюю память на диске - 'PageFile.sys'. Системе нет смысла перезаписывать на диск всю 4-Мбайтную модифицированную (грязную'D') страницу целиком. ОС берёт из кэша только 4-Кбайтную часть, и сбрасывает её на диск в виде кластера. Это сокращает время на диалог с тормознутым HDD. В страницах супервизора нет ничего-нового за исключением того, что ОС активно пишет только в них - все глобальные страницы грязные. Хотя, если-бы моя софтина была не 'HelloWorld', а записывала-бы какие-нить данные (например в переменные), то в них-бы тоже стояла метка (Dirty). Таблица-страниц содержит всего 467 записи, значит умножаем на 4-Мб (размер страницы) и получаем 1.868-Мбайт, т.е. почти всё 2-Гиговое пространство пользователя. Гораздо интересная часть лога содержится в разделе 'Physical'.. Здесь хранятся базы страниц в физической памяти, т.е. во-фреймах. Отличительной особенность плоской модели памяти является то, что сегменты и страницы могут начинаться с любого адреса, и системе не обязательно их выравнивать на какую-нить границу. Здесь вообще нет границ. Для эффективной работы, выравнивать нужно сам код программы, который потом загружается по виртуальному адресу пользовательского пространства. Возьмём из лога макс. 'Physical-адрес' 0x14D33000. Это физический адрес со значением 349.384.704, или 333-Мбайт от начала физ\памяти. Поскольку это база страницы, прибавим к ней размер одной страницы(4М), чтобы получить адрес хвоста страницы = 337-Мбайт. Нужно сказать, что именно такого размера ОЗУ у меня установлено на экспериментальной машине: 1-планка 256М, плюс одна 128М, равно 384-Мбайт общей памяти DDR1.
5
|
Эксперт Hardware
|
|
02.11.2017, 07:52 [ТС] | 7 |
ВИРТУАЛЬНАЯ ПАМЯТЬ
Подобравшись к виртуальной памяти на расстояние вытянутой руки, рассмотрим тонкости её функционирования. На данный момент картина такая., и мы (прикинувшись байтом) находимся внутри 'PageTable'. Справа, друг-на-дружке лежат страничные кадры, а слева - виртуальная память в виде записей PTE. Отмечу, что все секреты виртуальной памяти кроются именно на этом участке архитектуры, а всё\что слева - это аппаратная её реализация. То есть виртуальная память как сущность, есть ничто-иное как записи в таблице-страниц (PTE): На этой схеме изображена модель памяти систем класса NT (New Technology). C высоты птичьего полёта отчётливо просматривается вся её структура, и транспортный уровень адреса от самого ЦП и до физического пространства ОЗУ. На самом деле, это только внутри-процессорная часть, поскольку на этой схеме отсутствует контроллёр памяти, который преобразует абсолютный адрес, в DRAM-адрес ячеек памяти. На внешнюю шину-адреса, процессор выставляет именно DRAM-адрес (контроллёр памяти встроен в ЦП). В архитектуре, диапазон функционирования контроллёра памяти наглухо прикрыт аппаратными средствами и программисту не доступен. Он расположен непосредственно между таблицей-страниц и физ\памятью. 32-битный DRAM-адрес ячейки памяти включает в себя: номер модуля, номер банка в этом модуле, номер строки\столбца матрицы памяти, а так-же длинну пакета (поскольку ЦП никогда не читает из памяти 1-байт, а прихватывает в пакетном режиме ещё и рядом-стоящие (64 или 128), которые попадают в кэш процессора). Это отдельная тема, и к виртуальной памяти отношения не имеет. Она сама потянет на постов-так-надцать. Но вернёмся к виртуальной памяти... Алгоритм загрузки программы с диска. 1. Для создания нового процесса, система выстраивает новый 'РСВ - Process Control Block'. В этот блок скидывается всё окружение процесса - ProcessImage, таблицы IO\Memory\File, и пр. На определённом этапе, создаётся каталог-страниц 'PageDirectory', и его физический адрес загружается в регистр(CR3). 2. Теперь создаётся таблица-страниц 'PageTable', которая описывает виртуальное пространство процесса. Адрес базы этой таблицы, записью 'Entry' заносится в первое поле каталога-страниц 'PageDirectory'. Если общее кол-во страниц больше 1024, то создаётся ещё одна таблица-страниц, и ещё одна запись в каталоге. Образ программы на диске разбивается на 4-Кбайтные страницы, каждая страница нумеруется и ей присваиваются атрибуты. 3. Страницы диска проецируются в вирт\память процесса записями 'PTE - PageTableEntry'. Кол-во записей в этой таблице, равно кол-ву виртуальных страниц в образе файла на диске. Помимо атрибутов, в каждой из страниц хранится предполагаемый адрес расположения виртуальной страницы в страничном кадре. То есть Physical-адреса баз свободных фреймов в памяти. 4. У всех записей РТЕ сбрасывается "бит присутствия страницы в памяти" (флаг Present=0). Важно понять, что виртуальное пространство в начале процесса полностью пустое! Управление передаётся на точку-входа в программу, и первая-же инструкция приводит к 'PageFault' - страничное исключение(#PF). 5. В этот момент, супервизор страниц PUSH-ит CS:EIP (запоминает запрос), и кладёт в регистр процессора(CR2) адрес затребованной страницы. Теперь управление принимает обработчик 'PageFault', который по содержимому CR2 находит эту страницу в записях PTE, и загружает её из дисковой памяти в ОЗУ. На заключительном этапе, супервизор снимает со-стека CS:EIP и просит ЦП повторить запрос, после чего выполнение кода начинается\продолжается в штатном режиме. ----------------------------- От сюда следует, что никто-ничего заранее не подгружает, а всё загружается через 'PageFault' по-требованию!. Можно с уверенностью утверждать, что безграничное пространство виртуальной памяти толстой цепью привязано к обработчику 'PageFault' - отработавшие и пока не нужные страницы выгружаются из страничного фрейма в файл-подкачки 'PageFile.sys' (они могут ещё пригодиться), а на их место подгружаются новые затребованные страницы. Теоретически, таким-Макаром можно работать хоть с петабайтными файлами, лишь-бы в ОЗУ было место под пару\тройку дисковых страниц, а остальное организует сам 'PageFault' по записям из PTE. Добрую сотню страниц файла можно отображать по очереди даже в одном страничном кадре ОЗУ, только работать такая машина будет со-скоростью улитки, поскольку всё процессорное время будет уходить на подкачку страниц из диска. RVA и VA-адреса памяти. В дизассемблерах и отладчиках можно встретить адреса вида VA и RVA. RVA-адрес - это 'Relative Virtual Address', или относительный (чего-то) виртуальный адрес. Обычно этот тип адреса используют HEX-редакторы и дизассемблеры, например 'W32Dasm': Код
Disassembly of File: hWorld.EXE Number of Objects = 0003h, ImageBase = 00400000h ^^^^^^^^^^^^^^^^^^^^^ Object01: .text RVA: 00001000 Offset: 00000200 Size: 00000200 Flags: 60000020 Object02: .idata RVA: 00002000 Offset: 00000400 Size: 00000200 Flags: C0000040 Object03: .data RVA: 00003000 Offset: 00000600 Size: 00010200 Flags: C0000040 //----------- Program Entry Point ------------- :00401000 6A01 push 00000001 :00401002 680F304100 push 0041300F ...... Образ программы загружается по адресу 00400000h вирт\пространства (ImageBase). Занимать нижние адреса никак нельзя, поскольку там находится база 00010000h системных драйверов, и 64-Кбайтная запретная зона системы для вылавливания блох в виде нулевых указателей (64Кб=0FFFFh). Поэтому загрузчик страхуется и отбрасывает базу образа по-дальше. Как видим, все эти области вплотную прижаты друг-к-другу: буфер, драйвера, прикладная задача. Если сложить Base+RVA, то получим виртуальный VA-адрес, которым и оперирует процессор ('Entry_Point' на скрине выше). Мы опять вернулись к истокам, с чего и начинался весь этот разговор (jmp Post1). В некоторых источниках, виртуальный адрес называют ещё логическим, хотя между ними нет никакой разницы. Разброс и коллизия страничных кадров Вернёмся к логу выделенных процессу страниц из предыдущего поста, и посмотрим на диапазон линейных адресов 'Range'. Он принадлежит страницам файла на диске: Код
>> page Page Directory Physical 0578B000 Physical Attributes Linear Address Range ---------------------------------------------------- 05794000 P A U RW 00000000 - 003FFFFF 05792000 P A U RW 00400000 - 007FFFFF 1034B000 P A U RW 77C00000 - 77FFFFFF 08524000 P A U RW 7C800000 - 7CBFFFFF 14D33000 P A U RW 7F400000 - 7F7FFFFF ..... Но посмотрим на адреса физических фреймов 'Physical'. Почему они выравнены не на 4-Мбайтную границу (как виртуальные страницы), а на границу 1000h-байт? (3-младшие тетрады равны нулю, значит 12-бит или 4Кб). Ясно.. Значит в отличии от вирт\страниц, физические кадры всё-таки 4-Кбайтные. То есть под одну 4-Мбайтную виртуальную страницу, выделяются сразу 1024 4-Кбайтных фрейма. Вот они замутили.., хотя для выгрузки "грязных" страниц из кэша, это самый оптимальный вариант. Следующий немаловажный момент, это способ отображения виртуальных страниц на страничные кадры. У первых\двух страниц вроде наблюдается хоть какая-то последовательность, зато третья страница отброшена системой почти-что в хвост физ\памяти. Начиная с четвёртой.., строй вообще нарушается, что приводит к полнейшему хаосу. На выходе, получаем паутину приблизительно такого вида: Вот она - фрагментация памяти! При таком раскладе, после закрытия приложения система освободит все выделенные процессу ресурсы, и физическая память станет похожа на улыбку хоккеиста с выбитыми зубами. Не радужная перспектива.. Придётся запускать дефрагментатор памяти, который попытается собрать все страничные кадры активного процесса в одном месте, путём перемещения их с поправками в PTE. Глобальные страницы памяти Среди общего пула виртуальных страниц, есть страницы с атрибутом(G) - 'GlobalPage'. Эти страницы активно используют драйвера и сама система. Они никогда не выгружаются из фреймов и кэша-TLB, даже при перезагрузке регистра(CR3) в момент переключения задач. Глобальная страница выделена на рисунке выше красным, и к ней могут обращаться несколько процессов для повышения производительности (смотрим на страницы с битом 'G'). Код
>> page Page Directory Physical 0578B000 Physical Attributes Linear Address Range ---------------------------------------------------- 08524000 P A U RW 7C800000 - 7CBFFFFF 14D33000 P A U RW 7F400000 - 7F7FFFFF 01000000 P G D A S RW 4M 81000000 - 813FFFFF 01400000 P G D A S RW 4M 81400000 - 817FFFFF 01800000 P G D A S RW 4M 81800000 - 81BFFFFF 01C00000 P G D A S RW 4M 81C00000 - 81FFFFFF ..... Менеджер виртуальной памяти растасовывает ссылки на глобальные страницы, в таблицы-страниц всех задач в результате чего эти страницы получаются общими. Через них, процессор проникает на ядерный уровень при вызове системных API, и не нужно для этого переключать задачу.
4
|
Эксперт Hardware
|
|
21.11.2017, 01:04 [ТС] | 8 |
Общие принципы чтения данных из ОЗУ Не секрет, что при обмене с памятью, ЦП никогда не оперирует байтами, а использует только "пакетный режим". Длину пакета задаёт параметр "BL - Burst-Length". Смысл пакетной обработки в том, что на один адрес столбца контроллёр памяти отзывается чтением сразу нескольких последующих столбцов в строке. Логика DRAM-ядра имеет счётчик наращивания адреса столбцов, который и привязан к параметру "Burst-Length". Посмотрим на диаграмму ниже.. На ней просматривается значение этого параметра на шине "Data", которое в данном случае равно 4. Контроллёр даже не дожидается окончания чтения первого пакета-данных, и через несколько тактов сразу выставляет адрес следующего столбца, который вычисляется прибавлением значения(BL), к адресу предыдущего столбца. Таким образом, указав всего два адреса, контроллёр читает сразу 8-байтов. Отдельного внимания заслуживает управляющая линия "Command". Именно она задаёт всем темп, и пинает отстающих. Сигнал "ACT - Activate" приходит вместе со-стробом RAS# и открывает строку. "NOP" - он и в Африке ноп, и представляет из-себя передышку. Заканчивает цикл обмена с памятью команда "Prechange", которая снимает с регистра-защёлки ядра адрес открытой строки, и одним махом отправляет в неё все байты из усилителя "Sense-AMP" - регенерация DRAM-строки памяти. Тонкости работы ядра на аппаратном уровне рассмативаются ниже. Внутренняя архитектура DDR-SDRAM Синхронная память "DDR - Double Data Rate" пришла на смену устаревшей "SDR - Single Data Rate". Всю подсистему памяти SDRAM (Synchronous Dynamic Random Access Memory - синхронная динамическая память с произвольным доступом к данным) можно разделить на 3 функциональных узла: 1. Ядро памяти SDRAM. Узел обработки и хранения запоминающих элементов. Состоит из матрицы 1-байтных ячеек, дешифраторов строк и столбцов, регистров-защёлок адресов, логики управления, и усилителя\буфера "Sense-AMP". По большей части, одинаково для всех типов памяти - как SDR, так и DDR. 2. Буфер ввода-вывода I/O. Служит для промежуточного хранения данных. Именно в буферах кроются основные отличия SDR от DDR2-3-4. Модуль I/O построен на мультиплексоре MUX, который в порядке очереди сливает данные из буфера, для передачи их драйверу внешней шины. (мультиплексоры имеют несколько входов и один выход - чтение, демультиплексоры - наоборот, один вход и несколько выходов - запись). 3. Драйвер внешней шины-данных управляет 64-битной транспортной магистралью от памяти к процессору. Как-правило работает на более высокой частоте, чем частота DRAM-ядра и буферов I/O. На рисунке ниже, приведены основные отличия трёх поколений DDR. Четвёртое мало чем отличается от тройки (кроме как работа выходных каскадов на более высокой частоте), поэтому здесь она не рассматривается. Как видно, слабым звеном в этой цепочке является само ядро памяти, из-за барьера рабочей частоты - она не может быть больше 200-MHz. Ограничивают её физические свойства конденсаторов динамической памяти. На более высоких частотах мы просто не успеем считать заряд с их обкладок, что приведёт к искажению данных: Основным достоинством линеек памяти DDR, является т.н. "архитектура 2n-Prefetch", о чём могла только мечтать старушка-память SDR. Во-первых, все узлы SDR работали синхронно на одинаковой частоте, которая не превышала порога в 133-MHz (PC-100,133), а во-вторых - от ядра к буферу была только одна 8-битная линия передачи. Ну и в третьих - у SDR не было дифференциального (второго) клока у драйвера шины. По фронту одного такта можно было передавать только 1-байт данных, чего вполне хватало для писю'шек тех времён. Другое дело DDR-SDRAM, в которой учли все недостатки SDR. Модернизация началась с того, что от буфера к ядру добавили ещё одну 8-битную шину, и ввели понятие "2n-Prefetch". Два - это две шины к ядру (Double-Data-Rate), "N" - это размер шины (как-правило 8-бит), и "Prefetch" - означает предвыборку данных. Рассмотрим работу памяти по схеме "2n-Prefetch" на примере DDR1.. Весь массив делится на 4 независимых банка памяти (у DDR3 их 8). Каждая из упомянутых выше "2n-шин" соединяются c отдельным банком. Когда контроллёр памяти посылает сигнал активации строки ACT и RAS#, то указанная строка открывается сразу во-всех банках памяти. То есть мы получаем сразу несколько активных строк, и можем чередовать чтение из них. Нужно сказать, что начиная с DDR2, режим чередования банков - "Interleaving Mode" - поддерживается уже на аппаратном уровне. Доступ к данным ядра осуществляется попарно. Каждая команда чтения приводит к отправке по внутренней 2n-шине, двух байтов. Аналогично и в схеме DDR2.., только шин здесь уже не 2, а 4, и обмен осуществляется в 4-байтном режиме. Именно поэтому длина-пакета(BL) для DDR1 не может быть меньше двух, а для DDR2 - не меньше 4. Из DDR-3 (которая здесь не показана) сделали вообще монстра с ядерной шиной аж "8n", и соответственно банков в ней тоже 8: Для синхронизации работы буферных регистров с ядром, DDR использует одну и ту-же частоту 200 MHz, хотя выходной "мультиплексор MUX", работает уже на вдвое\большей скорости - 400 MHz, по очереди опрашивая регистры буфера. Эти данные принимает уже драйвер внешней шины, который и передаёт их непрерывным потоком процессору. Дифференциальный тактовый импульс драйвера (второй импульс смещён на пол-такта, см.пред.рис.) даёт возможность передавать данные как по-фронту первого импульса, так и по-фронту второго, переключая входы мультиплексора на удвоеной частоте. Подобным образом работает и DDR-2,3.., только на более высоких частотах. Диаграммы чтения памяти DDR-1,2 выглядят как на рисунке ниже (без сервисных сигналов). Чтобы не забивать пространство, для DDR-2 указана длина-пакета равная единице, хотя на самом деле, для этого типа памяти она не может быть меньше 4 - т.е. пакетный режим отключён: Принципиальное отличие DDR3 от 2 заключается в механизме "8n-Prefetch" вместо четырёх. Для его организации, необходимо, чтобы буфер работал на 4-кратной частоте ядра, а мультиплексор - на 8-кратной. Это позволяет за каждый такт памяти снимать с ядра по 8-байт данных, но если учесть пакетный режим (а для DDR3 BL=8), то получается вообще 64-байта, которые через внешнюю шину-данных глобальным пакетом попадают прямиком в кэш-память процессора - "64-byte cache-line".
6
|
Эксперт Hardware
|
|
21.11.2017, 01:21 [ТС] | 9 |
Сообщение было отмечено Mikl___ как решение
Решение
Устройство DRAM-ядра
Поверхностно разобравшись с транспортным уровнем, заглянем внутрь ядра динамической памяти. Запустим любой софт для сбора инфы о железе (например "HWiNFO32") и перейдём в раздел, где указаны данные SPD. Именно в этой крошечной 8-pin м/схеме зашиты все характеристики применяемых в данном модуле чипов. Размер SPD всего 256-байт, и для каждого типа памяти, описание имеет свой формат: Код
[SPD - Serial Present Detect] ------------------------------------------------------------- Memory Module(0) : 2Gb, PC3-12800, DDR3-SDRAM, SO-DIMM Row Address Bits : 15 Column Address Bits : 10 Number Of Banks : 8 Number Of Ranks : 1 Device Width : 8 bits Bus Width : 64 bits Но вернёмся к логу... Для адресации матрицы каждого из восьми чипов выделяются: 15-бит для строк (Row), и 10-бит для столбцов (Column), а раз так., значит матрица имеет размер: 32768-строки и 1024-столбца (ячейка: 1-байт). Напомню, что это только один чип, а всего их 8. PUSH'-им этот факт и едем дальше... Смотрим на поле "Number of Banks: 8", которое прямым текстом сообщает, что пространство каждого из чипов разбито на 8 независимых банков (модули до 1Gb имеют 4-банка, свыше - 8). Для их адресации достаточно 3-х бит. Инженеры обозвали эти биты BA[0-2] - Bank-Activate. В организации DRAM-ядра, банки накладываются блоками друг на друга. То есть, 3-банк'овских бита есть ни что-иное, как старшие биты строки. Получаем 18-бит для адресации всех строк матрицы одного чипа, без учёта банков. Итого в одном чипе: Код
Строк : 32.768 * 8 банков = 262.144 (18-бит); Столбцов : 1024 (10-бит) Ёмкость чипа: 262144 * 1024 = 268.435.456-байт, или 256-Mb (один чип-памяти). ------------- +-+---> Выбор банка(BS) Диапазон строк | | ________________ Банк(0) = 000.111.1111.1111.1111 //-- 000000...032767 Банк(1) = 001.111.1111.1111.1111 //-- 032768...065535 Банк(2) = 010.111.1111.1111.1111 //-- 065536...098303 Банк(3) = 011.111.1111.1111.1111 //-- 098304...131071 Банк(4) = 100.111.1111.1111.1111 //-- 131072...163839 Банк(5) = 101.111.1111.1111.1111 //-- 163840...196607 Банк(6) = 110.111.1111.1111.1111 //-- 196608...229375 Банк(7) = 111.111.1111.1111.1111 //-- 229376...262144 | | +----------------+------> 15-битный адрес строки Теперь ответим на вопрос: -"Как адресовать 8192-столбцов 10-ю битами?" Здесь уже интересней... Для согласования с внешней шиной, при сборке модуля шины-данных всех чипов соединяются последовательно, в то время как шина-адреса разводится по всем чипам параллельно. Это важно понять! То-есть 8.192 - это кол-во виртуальных столбцов в глобальной матрице, хотя адресуемых по-прежнему остаётся только 1.024 (10-битный адрес). Перед тем как выбрать столбец, контроллёру нужно вычислить, в каком из восьми чипов находится этот столбец. Для этого имеются сигналы активации чипов "CS - Chip-Select". Этих сигналов всего 4 - CS[0-3]. Их комбинацией можно выбрать один из 16-ти чипов. Число 16 выбрано не случайно, а с запасом для 2-ранковых модулей памяти, в которых общее кол-во чипов не 8, а 16. Для 1-ранковых модулей, старшая линия(CS) всегда будет сброшена в ноль. То есть 4-бита, которые используются для выбора чипа, являются старшими битами адреса-столбца. Получили 10+4=14 битный адрес, которым можем адресовать уже не только 8.192 столбцов, но и (Dual-Rank) с его 16.384 столбцами. При этом ёмкость модуля увеличится вдвое: 262144*16383=4Gb Код
+--+---> 4 линии(CS) | | +--------+---> Диапазон столбцов Чип(0) = 0000.11.1111.1111 ---- 0000..1023 Чип(1) = 0001.11.1111.1111 ---- 1024..2047 Чип(2) = 0010.11.1111.1111 ---- 2048..3071 Чип(3) = 0011.11.1111.1111 ---- 3072..4095 Чип(4) = 0100.11.1111.1111 ---- 4096..5119 Чип(5) = 0101.11.1111.1111 ---- 5120..6143 Чип(6) = 0110.11.1111.1111 ---- 6144..7167 Чип(7) = 0111.11.1111.1111 ---- 7168..8192 | | +----------+----> 10-битный адрес столбца Операция чтения начинается с того, что контроллёр памяти выставляет адрес нужной строки, и подтверждает его стробом RAS# - "Row-Address-Strobe". Приняв этот строб, логика ядра открывает нужную строку, но поскольку адресные линии разводятся по чипам параллельно, то указаная строка открывается сразу во-всех чипах памяти. Общую для всех чипов строку называют "страницей DRAM-памяти". Открытие страницы приводит к тому, что все её байты скатываются в усилители "Sense-AMP" (у каждого чипа свой усилитель). А сколько в одной DRAM-странице байт-то? Нетрудно догадаться, что размер страницы равен общему кол-ву столбцов в данном модуле - 8192. После того, как эти 8Kб данных благополучно разместятся в буферах 'Sense-AMP', контроллёр выставляет на шину адрес столбца затребованной ячейки памяти, и так-же подтверждает его стробом, только на этот раз CAS# - "Collumn-Address-Strobe". Теперь, логике ядра ничто не мешает выбрать из памяти байт, используя адрес столбца в качестве смещения в буфере 'Sense-AMP', и приступить к передачи пакета данных. При этом, активным остаётся "Sense-AMP" только того чипа, на котором в данный момент присутствует сигнал выбора чипа(CS#). Отключение остальных чипов обрезает DRAM-страницу с 8-ми, до 1Кб. На рисунке представлена схема чипа DDR-SDRAM (4-банка), где отлично просматривается топология отдельных узлов памяти: Код
ADD - MA - мультиплексная шина-адреса; DQi - 8-битная шина-данных чипа. CLK - Clock - тактовая частота (100..200-MHz); CKE - ClockEnable - отключение клока для энерго\сберегающего режима; RAS - строб адреса-строки; CAS - строб адреса-столбца; CS# - ChipSelect - активация чипа (раньше было 8-линий, для каждого чипа свой CS#); WE# - WriteEnable - разрешение записи в чип (открытие вх.буфера); DQM - DataMask - маскирование отдельных байтов (отключает ненужные DEMUX при записи);
3
|
Эксперт Hardware
|
|
21.11.2017, 01:29 [ТС] | 10 |
Особенности работы контроллёра памяти
Процессор взаимодействует с ОЗУ через контроллёр памяти "МС - Memory Controller". Этот контроллёр отвечает за физическую поддержку модулей SDRAM, а точнее за инициализацию, регенерацию чипов, установки таймингов, выбор тактовой частоты и другие\технические детали. У каждого канала памяти свой МС. Для сокращения общего кол-ва внешних линий, адресные входы чипов-памяти мультиплексируются. Адрес делится на 2 части. Сначала задаются старшие адресные биты, выбирающие строку массива ячеек. По стробу(RAS#) эти биты сохраняются в регистрах-защёлках чипа. После этого, на те-же адресные линии подаются младшие адресные биты для выбора столбца массива, которые так-же сохраняются в защёлках по стробу(CAS#). Однако процессор задаёт весь адрес целиком, одновременно помещая все его разряды на шину адреса. Их мультиплексирование выполняется контроллёром памяти. В ответ на запрос обращения процессора к ОЗУ, контроллёр принимает от него полный физический адрес и сигнал определяющий операцию - R/W. Затем он по очереди пересылает в ОЗУ адрес строки и столбца по мультиплексной шине(МА), фиксируя их стробами RAS/CAS соответственно. Шина-данных контроллёру не нужна, поэтому она соединяет процессор и память напрямую: Таким образом, в дополнение к мультиплексированию адреса, контроллёр памяти осуществляет ещё и генерацию сигналов RAS#, CAS#, CS# и WE#. При использовании чипов DRAM без само-регенерации, контроллёр отвечает ещё и за выдачу сигнала(А10), который управляет процессом регенерации строк матрицы. Сейчас контроллёры освободили от этой задачи - буквально все современные чипы поддерживают регенерацию ячеек памяти по своему внутреннему счётчику, на автомате. Характеристики модулей памяти Так уж сложилось, что в 2000-году вместо "конца света", на свет появилась первая память DDR. С этого момента частоту стали разделять на реальную и эффективную. Связано это было с дифференциальным клоком драйвера внешней шины. Маркетинг поспешил воспользоваться этой фишкой и стал на маркировке(PC) указывать не рабочую частоту модуля памяти (как это было у SDR), а его пропускную способность. Чтобы получить полезную нагрузку шины, нужно её разрядность (как-правило 8-байт) умножить на эффективную тактовую частоту: Из этой таблички видно, что после PC133 сразу-же идёт PC1600. Как такое может быть? 10-кратное увеличение производительности за один шаг! Вот жулики... Это-же прокаченая PC200, которую теперь называют DDR-200. Но поскольку у новоиспечённой памяти были и плюсы в виде архитектуры "2n-Prefetch", то все проглотили эту наживку и успокоились. Ход маркетологов заслуживает апплодисментов! Помимо этого, модули принято разделять и по форм-фактору: 1. SIMM (Single In-Line Memory Module). Асинхронная динамическая память. Пусть покоится с миром.. Древний 72-контактный модуль, с односторонним расположением выводов. На второй стороне контакты дублируются. Устаревший, и давно покинувший рынок вариант. 2. DIMM (Dual In-Line Memory Module). Могут иметь до 240-независимых пинов (по 120 с каждой стороны). Применяется во всех современных компьютерах. 3. SO-DIMM (Small Outline DIMM). Компактный вариант DIMM для ноутбуков. Поддерживает стандарты DDR(2,3). Популярны 200-контактные модули. 4. Micro-DIMM. По размерам меньше чем SоDIMM и доступны в вариантах: SDR 144-pin, DDR 172-pin, DDR2 214-pin. Как-правило применяется в планшетах, и прочих малогабаритных девайсах. 5. RIMM (Rambus In-Line Memory Module). Форм-фактор модулей типа DR-SDRAM (Direct Rambus SDRAM). Имеют до 242-контакта, и чаще применяются в серверных платформах. Из-за высокой стоимости, в РС практически не встречаются. Особенностью является увеличение частоты за счёт уменьшения разрядности шины.
3
|
Эксперт Hardware
|
|
01.12.2017, 08:20 [ТС] | 11 |
Внешняя шина памяти (системная шина процессора)
Поскольку SDR - Single-Data-Rate, DDR - Double-Data-Rate, то DDR2 должна быть QDR - Quadra-Data-Rate, т.к. данный стандарт подразумевает в 4-раза большую скорость передачи по сравнению с SDR. А ведь термин "QDR" существует-же в доках INTEL. Посмотрим на лог, описывающий характеристики системной шины одной из устаревших мат-плат с чипсетом i845: Код
Общая информация ------------------------- NorthBridge..: Intel i845D SouthBridge..: 82801BA (ICH2) LPC Controller NorthBridge Information ------------------------- Architecture.: HUB Bus Speed....: 101.0 MHz FSB Speed....: 403.8 MHz (QDR) Ясно, что если разница между Speed'aми 4-кратная и на горизонте маячит поправка QDR (Quadra=4), то между ними явно должна быть какая-то связь. На самом деле "QDR" - это тип системной шины FSB, в которой применяются два дифференциальных клока. Такая схема позволяет передавать 4-байта за такт шины. Нужно сказать, что это не единственный тип в своём роде, но обо всём по-порядку.. Модернизация архитектур МП-систем приводит к расширению функций чипсета, изменяются подходы к его построению. Чипсетам для i286 нужно было всего-лишь связать шину ЦП с несложным контроллёром памяти, и подключить к этой связке шину ISA. Для i486 возможностей ISA уже не хватало, и стали появлятся новые шины. Процессор соединяется с памятью посредством системной шины FSB - Front-Side-Bus, от пропусной способности которой зависит общее быстродействие системы. На физ. уровне, современная FSB - это 64 дорожки на печатной плате. Ёмкость каждой из дорожек 1 бит - получаем 64-битную шину, по которой в разные промежутки времени передаются адрес и данные (64-бит = 8-байт). Разнообразие шин в системе Шины отличаются назначением (внутренняя, интерфейсная), разрядностью (16/32/64-бита), способом передачи информации (последовательный или параллельный), пропускной способностью Мбайт/с, и кол-вом поддерживаемых устройств. Она может быть синхронной (передача только по тактам), асинхронной (передача без привязки по-времени), а так-же мультиплексной (передача адреса/данных по одним и тем-же линиям, по-очереди). История развития МП-систем доказала, что организация обмена по шинам гораздо важнее, чем особенности процессоров, ведь шины живут намного дольше. Поэтому инженеры ориентируются на уже существующие стандарты шин при разработке своих новых процессоров, т.е. шины оказываются чуть-ли не главным фактором в архитектуре системы. Ниже приведены характеристики параллельных шин.. Основным параметром шины является пропускная способность в Мбайт/сек (MHz * разрядность шины-данных в байтах). Чем выше этот параметр, тем шина считается производительней, и по ней можно передать больше данных за один её такт: Код
Шина МГц Мбайт/с Данные Адрес ---------------------------------------------------- HT v3 2000 16000 8-байт 32/64 FSB 4x 1600 12800 8 32/64 PCI–E 16х 533/1066 4264/8528 4/8 32/64 AGP 8x 133/266 1064/2128 4/8 32/64 PCI 33/66 132/264 4/8 32 VLB(VESA) 33 132 4 30 Card Bus 33 132 4 32 MCA 20 76 4 32 LPC 16 64 4 32 EISA 10 33 4 32 ISA 8 16 2 24 ---------------------------------------------------- HT - Hyper Transport (AMD) Ping-Pong Mode FSB - Front Side Bus (х4 = макс.1600 MHz) AGP - Accelerated Graphics Port (2х,4x,8x - множители MHz) PCI - Peripheral Component Interconnect (Express) VLB - VESA Local Bus LPC - Low Pin Count MCA - Micro Channel Architecture ISA - Industry Standard Architecture (Extended) Протоколы шин требуют, чтобы любое из устройств на шине могло: 1. Распознать свой адрес на шине-адреса; 2. Распознать на шине-управления действие, которого ждёт от него ЦП (R/W); 3. Выполнить это действие, и передать результат в ЦП через шину-данных. Эти три действия составляют один цикл обмена, и называются "шинной транзакацией". Инициатором транзакаций может быть как сам ЦП, так и любое устройство, способное быть "мастером". Генератор тактовых импульсов Теперь сделаем упор на тактовую частоту... На материнской плате, всё синхронизируется от опорного кварца, который вырабатывает всего одну частоту 25-MHz. Это глобальный метроном для всех устройств в системе. Если какому-то из устройств требуется более высокая частота, то к 25 применяется соответствующий множитель, если-же нужна частота с большей длительностью, то её получают через делитель. Реализуется это ответвлением от опорной линии, с нужным временем задержки. Таким образом порождается вторичный сигнал, который сдвинут по фазе относительно исходного: Теперь каждой шине можно задать свою частоту: HT, FSB, DMI, PCI-E, PCI, LPC и прочие. На старых платах опорный кварц имел частоту 14,318 MHz, поэтому её оставили для совместительства. Кроме того, девайсы могут иметь свои синтезаторы частот, работа которых должна быть синхронизирована с системными 25-MHz. Ещё нужна "обратная связь" с выхода на вход по всем частотам. Клокер имеет схему сравнения импульсов и если они не равны, значит на шине висит неисправное устройство и шину пора вырубать. INTEL собирает генераторы тактовых импульсов на м/схеме 9250, или более современном её аналоге 950201. Рисунок демонстрирует общие принципы работы этого генератора: Роль клокера в системе нельзя недооценивать. К примеру, инструкция ассемблера "HALT" совсем отключает поступление тактовых импульсов на процессор, а в энерго/сберегающем режиме частота системной шины FSB уменьшается в несколько раз, в результате чего ЦП становится неповоротливым и как-бы засыпает. Эффективные частоты ЦП, памяти и шины FSB Процессорная шина FSB может работать на физических частотах клокера: 100, 133, 166, 200, 266, 333 и 400 MHz. Эту частоту называют ещё реальной частотой шины процессора. Одну из этих-же частот использует и системная память с процессором. То есть, реальная частота шинного драйвера DDR, системной шины FSB и процессора CPU - всегда одинакова! Иначе они не смогут работать синхронно! Дальше, перечисленные устройства применяют к общей реальной частоте свой множитель (Multiplier), в результате чего все они работают на разных частотах, но с одним периодом. Для всех плат INTEL множителем FSB является значение(х4), а для памяти - множитель(х2). Это константы, поэтому если эффективная частота FSB=800MHz, а DDR=400MHz, то говорят, что соотношение FSB/DRAM равно 1:1, а не 1:2. Реальная (опорная) частота FSB для этого примера будет иметь значение 200MHz. Множитель(х4) напрямую связан с типом системной шины FSB. В большинстве случаях - это упомянутая выше шина типа QDR (QPB - Quad-Pumped-Bus), хотя бывают и клинические случаи. Шины первых процессоров Intel были типа GTL, а у AMD - EV6. Для них, множителем будут значения х1 и х2 соответственно. Если сравнивать типы шин FSB с памятью ОЗУ, то шину EV6 можно было назвать DDR, а шину QPB - DDR2. В хвосте осталась-бы GTL, по аналогии с памятью SDR. Важно!!! Данный множитель(х4) для шины FSB относится только к платам INTEL, т.к. шина "Hyper-Transport" его конкурента AMD, функционирует по абсолютно другим принципам. Пока мы здесь рассматриваем исключительно конструктивные особенности INTEL, а детали шины AMD будут рассмотрены ниже. Если реальная частота системной шины ограничена с клокера значением 400-MHz, значит эффективная её частота может достигать макс.порога в 1600-MHz (400х4). Множитель системной шины имеет постоянное значение(х4), в то время как множитель ЦП зависит от типа процессора. Он лежит в диапазоне от х4 до х30 и может быть дробным. Поскольку в ядре процессора его коэффициент зафиксирован, то реальная частота ЦП зависит от частоты системной шины - при внешнем разгоне шины, повышается и частота процессора. Частоты периферийных шин типа PCI, AGP и прочии, не зависят от частоты FSB, а выходят с клокера отдельными линиями. Рассмотрим пример, когда реальная частота FSB равна 333 МГц. Получается, что клокер генерит дефолтные 25-MHz, к которым его внутренние схемы применяют свой множитель: 13,32. Получили физ частоту шины FSB: 333 MHz (25 х 13,32). Теперь к физической, применяем интел'овский множитель шины х4, и получаем эффективную частоту FSB: 1332 MHz, которую и указывает производитель на материнской плате: Общая формула вычисления эффективных частот на мат\плате выглядит так: Код
FSB = FSB(физ) x4 DDR = FSB(физ) x2 ЦП = FSB(физ) x (множитель ЦП: 4..30) ------------------------------------------------ Азбука: при FSB(физ) = 333 MHz, множитель ЦП = 9 ЦП = 333 * 9 = 2997 MHz FSB = 333 * 4 = 1332 MHz DDR = 333 * 2 = 666 MHz ------------------------ FSB/DRAM Ratio = 1:1 От сюда следует, что если Вы решили обновить память на своей машине, то сначала нужно узнать частоту системной шины и выбирать модуль с частотой, кратной частоте FSB. Например, для указанной выше платы с FSB=1333MHz, идеальным вариантом будет "DDR2-1333 / PC2-10600" (буфер в/в = 667 MHz, см.таблицу в предыдущем посте). Тогда можно будет сказать, что Ваша система максимально оптимизирована по железу. Множитель ЦП есть величина не фиксированная. Одни производители уменьшают множитель, но повышают частоту FSB, а другие - наоборот. С характеристиками своего процессора можно ознакомиться на сайте https://www.overclockers.ua/cpu/info/: Код
[System Information]-------------- CPU Brand : Intel(R) Celeron(R) CPU 847 @ 1.10GHz CPU Code : Sandy Bridge-MB SV (BGA1023) CPU Clock : 100 MHz Multiplier : 8-11 [Processors Frequency]---------------- Low : 100.0 MHz х 8 = 800.0 MHz Hing : 100.0 MHz х 11 = 1100.0 MHz Current : 99.8 MHz х 11 = 1097.6 MHz Но раз есть фронтальная шина Front-Side-Bus, значит должна быть ещё какая-то? И она действительно существует - это внутренняя шина процессора Back-Side-Bus, которая работает на своей частоте. Эта шина соединяет между собой внутренние узлы самого процессора типа: ядро, кэш-память и прочие. Множитель ЦП как-раз и определяют частоту этой внутреней шины BSB. Таким образом, производительность шины является одним из важнейших параметров системы, а как стало ясно, заправляет всем генератор опорной частоты, или просто маленький клокер.
3
|
Эксперт Hardware
|
|
01.12.2017, 08:46 [ТС] | 12 |
Сообщение было отмечено Mikl___ как решение
Решение
Сравнение архитектур INTEL и AMD
Конкурентная борьба между двумя гигантами началась ещё в 1982-году с выходом в свет процессора i80286. Именно тогда AMD (Advanced-Micro-Device) подписала контракт с Intel на производство i8086, а уже в 83-году выпустила свой первый Am286 – точный клон i286, но работающий на вдвое большей частоте - аж 20 МГц. Am286 можно рассматривать как первый удар в конкурентной борьбе, которая длится уже 35-лет. В последующем Intel не раз пожалеет о своей оплошности, поскольку все клоны AMD работали на более высоких частотах, чем такие-же процессоры Intel. Чтобы разорвать этот договор, гигант не придумал ничего лучше, чем начиная с i80586 переименовать свою продукцию на Pentium (от греческого Penta - 5), поскольку контракт был подписан только на цифровую марку. Теперь AMD не могла уже тупо клонировать Intel - так появился AMD-K5 с частотой 133MHz, как первая попытка собственной разработки. Технически, он был более совершенным чем Pentium, но его недостатком стала низкая частота, поэтому он не смог нанести ожидаемый нокаут Пенте. (есть серьёзное предположение, что литер "К" в названии К5 выбран в честь Супермена, который прилетел с планеты "Криптон". по другой версии - он означает "Kryptonite" - вещество, лишающее Супермена силы. под Суперменом подразумевалась Intel). Вершиной успеха AMD стал Athlon К7, который нанёс Intel сокрушительный удар! Он был наиболее успешным процессором со времен Am386. В 2000 году в дополнение к интеловскому Р4, AMD выпускает процессор Duron и полностью покоряет бюджетный сектор рынка, оставив Intel далеко позади. Здесь Intel впадает в глубокий ногдаун, но пробудившись от спячки опять начинает штурмовать процессорный мир со своей новой архитектурой Core-2. На этот раз Intel пошла другим путём и сделал упор не на тактовую частоту, а на более длинный конвейер. Исходя из предыдущего опыта, средства массовой информации с осторожностью отнеслись к рекламе "Core-2", но к разочарованию AMD, он полностью соответствовал заявленным возможностям. В результате, общая расстановка сил в "турнирной таблице" по году выпуска выглядит приблизительно так (прочерк - прошущеный удар, когда нечем ответить): Код
INTEL | AMD ----------------------------------|---------------------------------------- 80286 – 12 Mhz, FSB (GTL) | Am286 – 20 Mhz, FSB (GTL) 80386 – 33 Mhz | Am386 – 40 Mhz 80486 – 100 Mhz | Am486 – 120 Mhz Pentium – 233 Mhz, FSB (AGTL) | Am586 – 133 Mhz Pro – 200 Mhz | K5 – 133 Mhz Xeon – 233 Mhz | K6 – 300 Mhz Celeron – 3.2 Ghz | K6-II – 550 Mhz ----- | K6-III – 570 Mhz Pentium-4 – 3.8 Ghz, FSB (QPB) | K7-Athlon – 1.4 Ghz, EV6 ----- | Duron – 1.8 Ghz ----- | Athlon XP – 2.2 Ghz Pentium D – 3.7 Ghz | Sempron – 2.3 Ghz ----- | K8-Athlon 64 – 2.6 Ghz, HT (1000 Mhz) Core 2 – 3.2 Ghz, QPI | ----- Dual-Core – 2.8 Ghz | ----- Core i7 – 3.2 Ghz | K10-Phenom – 3.7 Ghz, HT (2000 Mhz) Сейчас и Intel и AMD идут уже другим путём - объединяют под одним колпаком несколько ядер. Арифметика простая: чем больше ядер, тем выше производительность, но на практике получается по-разному. Некоторый софт просто не знает, что можно работать с несколькими ядрами, а некоторые - делают это плохо. Только у специально заточенных под многоядерность приложений наблюдается существенный прирост сил. Посмотрим на такую схему, где в грубой форме определены основные различия архитектур старого и нового поколений. Процессор через FSB подключается к контроллёру системной логики, который обычно называют северным мостом (потом их переименовали в хабы). Он имеет в своём составе контроллёр ОЗУ (сейчас MС встраивают уже в процессор), а так-же контроллёры шин периферии: Поскольку здесь мы обсуждаем память, то обратим внимание на кочующий образ жизни контроллёров видео и памяти (обозначены синим). На первых платах эти контроллёры были встроены в северный хаб - Graphic & Memory Controller Hub, но под натиском современных требований, системная шина FSB стала проседать не справляясь со-своими обязанностями. Инженерам пришлось перемести контроллёры DRAM и AGP внутрь процессора, чтобы подключить их к более высокоскоростной его внутренней шине. Это привело к тому, что 3/4 GMCH освободилось, и в него можно сбросить весь южный хаб - получился универсальный Platform Controller Hub, который соединяется с процессором или через последовательную шину DMI (Direct-Media-Interface), или-же более современном её аналоге UMI. До выхода на сцену AMD-Athlon, в архитектуре AMD не наблюдалось особых новшеств, т.к. это были просто клоны Intel - те же мосты с хабами и прочее. Но с появлением Athlon всё изменилось. Вслед за Intel, AMD так-же перешла к одно-хабовым решениям. Северный мост вместе с интегрированной графикой переехал в ЦП, а южный остался дополнительной схемой. Если Intel предпочитает для новых южных мостов термин "PCH", то в AMD избрали название FCH - Fusion-Controller-Hub, хотя с технической точки зрения чипы обоих производителей похожи друг_на_друга как близнецы. Одним из главных новшеств платформы AMD-K8 стало внедрение быстрой, двунаправленной параллельно-последовательной шины HyperTransport (HT) для обмена данными между ЦП и остальными узлами системы. Первые её версии работали на частоте 800/1000 МГц, что обеспечивает скорость передачи в 6-8 Гбайт/с. Отличительной особенностью этой шины является то, что её можно использовать и как внешнюю шину процессора, и в тоже время как внутреннюю, для связки нескольких процессоров между собой. Ответный удар от Intel на эту шину последовал чуть-позже. Её назвали QPI - Quick-Path-Interconnect. Принципы функционирования фронтальных шин Рассмотрим принципиальные различия системных шин, и способы передачи по ним данных. Как было сказано выше, на свалку истории отправилось уже приличное их кол-во, начиная от шин типа GTL до относительно недавних FSB. Они прослужили "отечеству" долгое время, поэтому заслуживают хоть какого-то внимания. Любой процесс в компьютерной системе начинается только фронту тактового синхро\импульса, т.е. по положительной его составляющей. Если тактовый импульс один, то ориентируясь на его фронт можно за такт передать только одну порцию данных. При 64-битной шине это получается 8-байтов за такт шины. Но если добавить ещё один синхро\импульс и сдвинуть его по-фазе относительного первого, то получим дифференциальный импульс с двумя фронтами, и значит сможем передавать уже вдвое больше данных за такт - первую порцию будем отправлять по фронту клока(1), а вторую порцию - по фронту клока(2). Иногда такой способ называют ещё передачей по обоим фронтам синхро\импульса: Шина GTL У системных шин FSB первого поколения типа "GTL - Gunning-Transceiver-Logic" тактовый импульс был один (не было импульса CLK#). Этот тип применялся для работы с памятью Single-Data-Rate (SDR). Поскольку макс.частота 64-битной шины GTL была 100MHz, то пропускная её способность не превышала 800 Мбайт/с. Шина QPB Появление памяти DDR потребовало от разработчиков новых типов шин, поскольку из-за GTL возникал эффект "бутылочного горлышка". Всё новшество заключалось в добавлении сначала ещё одного импульса Clock# (см.рис.выше), а потом к двум - на радостях прибавили сразу ещё два! Так на свет появилась квадро-шина "QPB- Quad-Pumped-Bus" с пропускной способностью х4 (от сюда и постоянный множитель интеловских шин х4). То есть при тех-же 100MHz, QPB передавала уже в 4-раза больше данных - 800х4=3200 Мбайт/с. Если GTL была способна передавать за так всего 8-байт, то QPB уже 32-байта. Эта шина стала наиболее удачным решением Intel, поэтому просуществовала она достаточно долго, вплоть до появления процессоров Intel Core2. Физическая частота 100MHz для неё не предел - она работала на макс.частоте 333MHz, что определяло её пропускную способность в (333*8)х4=10600 Мбайт/с. На рисунке показано техническое оформление тактовых импульсов на шине QPB (отсчёт ведётся от первого клока): Шина EV6 Теперь рассмотрим особенности системных шин AMD.. Первые их платформы были точными копиями Intel - это касалось и шины GTL. Но после того, как Intel разорвала в клочья совместный контракт, AMD ввела свою шину "EV6". Эта шина была разработкой компании DEC-Alpha, которая использовала её для своих процессоров "Alpha 21264". Данные ЦП имели кодовое название EV6, что расшифровалось как "Extended VAX" шестого поколения. AMD впервые применила эту шину в чипсете 751. У неё было всего 2-клока, поэтому она уступала по производительности интеловской QPB. EV6 работала на физ.частотах до 200MHz, ширина шины 72-бита (8-бит для коррекции ошибок ECC), соответственно пропуская способность EV6 была ограничена (200х2)*8-байт=3200 Мбайт/с. Шина Hyper-Transport Свет увидел эту шину вместе с процессором AMD-К8. Она стала по истине гипер-шиной всех времён и народов! Козырем был сам способ передачи данных - параллельно\последовательный. Нужно сказать, что в разработке этой шины (помимо самой AMD) принимало участие более (!)140 компаний, которые собрались под одной эгидой "HyperTransport Technology Consortium". Так чем-же HT заслужила такого внимания? Шина - последовательная, дуплексная (двухсторонняя), ширина 16-бит в одном направлении (в обоих - 32), способ передачи DDR, множители от х1 до х16 (дефолтный 5), физ.частота 200-MHz. Эффективная частота её одной жилы при х5 равна 1000-MHz, хотя в доках указывают HT2000, что определяет результирующую частоту в обе стороны (маркетинг рулит). Имеется автоопределение ширины-шины в диапазоне 2..32-бита, поэтому она легко масштабируется, позволяя использовать HT не только как внешнюю шину ЦП, но и как интерфейсную шину устройств типа PCI. Для согласования HT и PCI применяются НТ-мосты. Помимо мостов имеются НТ-тунели и свичи, для отвода вторичных жил от основной. Поскольку шина HT последовательная и двунаправленная (данные могут одновременно передаваться в обоих направлениях - дуплекс), то пропускная способность её вычисляется уже другим способом, а не как у параллельных шин FSB. Шина может работать и в полудуплексном режиме - в этом случае ширина её расширяется до 32-бит. Посмотрим на таблицу ниже.. За такт передаётся два пакета данных (DDR), поэтому для простоты расчётов - ширину умножаем на 2. Здесь НТ означает встречно\направленную передачу в обе стороны. Соответственно, чтобы получить общую пропускную способность, нужно значение НТ умножить на DDR: Код
Версия | Год | МГц(физ)| Множ | МГц(эфф)| HT | Ширина | DDR | Гбайт/сек -------|------|---------|-------|---------|--------|--------|--------|---------- 1.0 | 2001 | 200 | х4 | 800 | 1600 | 32 | 8-байт | 12.8 1.1 | 2002 | 200 | х5 | 1000 | 2000 | 32 | 8 | 16.0 2.0 | 2004 | 200 | х7 | 1400 | 2800 | 32 | 8 | 22.4 3.0 | 2006 | 200 | х13 | 2600 | 5200 | 32 | 8 | 41.6 3.1 | 2008 | 200 | х16 | 3200 | 6400 | 32 | 8 | 51.2 При увеличение частоты НТ задираются и частоты периферийных шин, что может отрицательно повлиять на такие устройства как SATA, PCI-Express и прочие. В сети достаточно примеров, когда оверклокеры увеличив частоту НТ - теряли при этом данные на харде. При множителе х5 (несмотря на относительно низкую пропускную способность 16-Гбайт/с) - HT её вполне хватает, ибо самое узкое место - контроллёр ОЗУ, вынесен за пределы шины внутрь процессора. Увеличение скорости работы шины (связывающей ЦП с чипсетом), важно только для машин с несколькими видео-картами. В этом случае карты начинают делить между собой пропускную способность шины PCI-E, поэтому есть резон чуть прибавить её частоту. Шина QPI (Intel) ..была разработана в 2008г для замены традиционной шины FSB. "QPI - QuickPath Interconnect" была призвана бросить вызов шине "Hyper-Transport". Используется для связи ЦП с чипсетом, но если платформа многопроцессорная - то и для связки нескольких ЦП друг с другом. Как и НТ - является последовательной, двунаправленной шиной и подразумевает, что контроллёр памяти встроен в ЦП. Ширина в каждую сторону (приём-передача) составляет по 20-бит (20 отдельных пар линий), при этом 16-бит отводится для передачи данных, 2 линии резерв для сервисных сигналов, и ещё 2 - для коррекции ошибок CRC. C учётом ещё двух пар линий тактовых импульсов (одна пара на приём, другая на передачу), получаем 42-пары линий. То есть QPI является 84-битной. Шина может работать на частотах от 2,4 до 4,8 GHz. Пропускная способность составляет 25,6 Гбайт/с в одну сторону, хотя для шин QPI и НТ такую единицу измерения теперь не применяют. Вместо неё введён термин "трансферов в секунду", т.е. число передач пакетов в секунду - GT/s (гиго-транзакаций). --------------------------------- Выводы.. AMD, и Intel - это разные архитектуры и поэтому сложно их сравнивать. Анализ эффективности каждого процессора AMD и Intel, это не очень хорошая идея, поскольку мы не можем со 100% уверенностью сказать, что конкретная модель Intel лучше, чем другая модель от AMD только потому, что у неё более высокая тактовая частота. Как-правило, скорость Intel всегда выше, чем у AMD.. Но это не означает, что процессоры Intel лучше. Высокая скорость совершает больше рабочих циклов в секунду, а не больший объём работы. У Intel есть тенденция делить задачу на множество мелких частей для более лёгкой обработки, поэтому объём работы за цикл относительно невелик. В отличие от Intel, у AMD рабочий цикл длится дольше, но он обрабатывает больше данных за такт. Таким образом, когда AMD суммирует общий объём проделанной работы, то результат получается довольно большим.
6
|
Эксперт Hardware
|
|
12.05.2018, 11:32 [ТС] | 13 |
Сообщение было отмечено Mikl___ как решение
Решение
Пора-бы уже поставить тут жирную точку и закрыть этот пост, но осталась ещё нераскрытая тема - это устройство кэш-памяти. Как и все/скоростные устройства, кэш глубоко зарыт внутри ЦП и как он функционирует на самом деле, наверняка знают только его разработчики. В манах вопрос освящается мутно и не хватает простых примеров, чтобы распутать сложные понятия - посмотрим на кэш с другой стороны..
Кэш-память процессора Работа кэш основана на принципе локальности обращений. Это уникальный механизм, способный предсказывать запросы к памяти более чем в 90% случаях, и это при соотношение размеров 1:100000 (4Gb/32Kb). Как показала практика, в любой момент времени программы используют только часть своего кода, которая реализует одни и те-же операции с несколько отличающимися данными. Затем переход к другой области памяти, и всё идёт по-кругу. Такое положение объясняется наличием циклов в коде, что играет кэшу на-руку. Ещё с рассвета архитектур, ЦП общается с памятью посредством параллельной шины. Остальные девайсы переходят уже на более высокоскоростной последовательный интерфейс (PCIe, USB3), однако шина памяти остаётся прежней - так было и будет, пока инженеры не придумают что-то взамен динамической ОЗУ. Именно DRAM тормозит весь тех/процесс, т.к. её ядро не способно превысить частотный барьер в 200 MHz - на более высоких частотах конденсаторы ячеек просто не успевают разряжаться. Динамическая DRAM хоть и тормознутая - зато большая и дешёвая, это и удерживает её позиции на рынке. Чтобы хоть как-то решить проблему DRAM, было решено добавить между процессором и ОЗУ небольшую прослойку в виде статической кэш-памяти SRAM, где запоминающим элементом служит уже не конденсатор, а триггер. Регистры самого процессора собираются на таких-же триггерах, поэтому скорость обмена ЦП с кэш-памятью имеет коэффициент 1:1. ---------------------------------------- В наше время, все операции с памятью выполняются только в пакетном режиме, процессор не может записать в ОЗУ байт или слово, он загребает за-раз сразу по 64-байта (шина=8, и счётчик BL=8), которые отправляет в свой кэш - '64-byte cache line'. Именно такой размер кэш-строки присущ буквально всем современным процессорам. Ясно, что в кэше хранится не одна строка, они собираются в блоки из N-строк - один такой блок называют банком кэш-памяти, или на их манер 'Way', каждая строка имеет свой индекс. Кол-во строк в одном наборе зависит от ёмкости кэш, и лежит в диапазоне от 32 до 8192. На рисунке ниже представлен банк из 64 кэш-строк. Если в одной строке 64-байта, а всего строк тоже 64, то такой кэш способен отобразить одну 4-Kбайтную страницу памяти (64x64=4096): Инженеры распилили общее пространство кэш на две части: в первой хранятся непосредственно кэш-строки, а во второй - их адреса. Адресное поле назвали тегом 'TAG', в которое сбрасывается не весь 32-битный адрес строки, а только старшая его часть. У каждой кэш-строки свой тег, разрядность тега зависит от размера и организации кэш - чем больше кэш, тем меньше битов в теге. То есть теговая память кэша(L1) будет размером больше, чем теговая память кэша(L2). В глазах кэша, мир существует в виде страниц физической памяти. Когда кэш смотрит на 4Kb страницу, то по индексу[0] он отображает у себя её байты 0-63, по индексу[1] - байты 64-127 и т.д. Такой шаблон повторяется для каждой страницы, поэтому данные третьей строки на странице[0], будут отличаться от данных такой-же строки на странице[1]. Но постойте... А куда мы собираемся отображать страницу[1] - в кэш-же пока имеется только 1-Way для нулевой страницы? Обстоятельства вынуждают нас добавить в структуру кэш ещё один Way, ..но раз-уж есть такая возможность, то добавим не один, а сразу 7-штук! Тогда получим заявленную производителями организацию '8-way cache'. Если в одном наборе(Way) мы могли отобразить одну страницу памяти, то теперь восемь - а это 32Kb памяти: Посмотрим на характеристики процессоров Intel из отчёта CPU-Z... Здесь видно, что каждое ядро процессора имеет свой кэш. Раздельные кэши для инструкций и данных имеет только L1. На всех уровнях L1-L2-L3 его организация отличается как по ёмкости, так и по кол-ву наборов(Way) в диапазоне 4..16. Вот тут-то и начинается самое интересное: Код
Name Intel Core i5 3230M Codename Ivy Bridge (2-ядра) Technology 22 nm L1 Data cache 2 x 32 Kb, 8-way set associative, 64-byte line size L1 Inst cache 2 x 32 Kb, 8-way set associative, 64-byte line size L2 cache 2 x 256 Kb, 8-way set associative, 64-byte line size L3 cache 3 MBytes, 12-way set associative, 64-byte line size -------------------------------- Name Intel Core i7 6700K Codename Skylake (4-ядра) Technology 14 nm L1 Data cache 4 x 32 Kb, 8-way set associative, 64-byte line size L1 Inst cache 4 x 32 Kb, 8-way set associative, 64-byte line size L2 cache 4 x 256 Kb, 4-way set associative, 64-byte line size L3 cache 8 MBytes, 16-way set associative, 64-byte line size Код
32Kb L1-cache (8-way)------------------------ 32Kb / 64-byte = 512 всего кэш-линеек 512 / 8-way = 64 индекса в одном наборе Way CPU address: Offset = 6-бит для выбора одного из 64-байтов в строке Index = 6-бит для выбора одного из 64-индексов Tag = 20-бит (старшая часть адреса) 256Kb L2-cache (4-way)----------------------- 256Kb / 64-byte = 4096 cache line 4096 / 4-way = 1024 index Address: Offset = 6-bit Index = 10-bit Tag = 16-bit 8Mb L3-cache (16-way)------------------------ 8Mb / 64-byte = 131072 cache line 131072 / 16-way = 8192 index Address: Offset = 6-bit Index = 13-bit Tag = 13-bit Рассмотрим детали реализации подробней... Длинна кэш-строки постоянна и равна 64-байтам. Для выбора одного из байтов строки требуется 6-бит - это младшие биты адреса, который процессор выставил на шину. В то-же время разрядность поля индекса уже не так постоянна, и зависит от ёмкости кэш и наборов(Way) в нём. Оставшиеся старшие биты адреса отправляются прямиком в теговую память. Посмотрим на следующий рисунок, где для тега выделяется 20-бит (типичный L1-кэш ёмкостью 32Kb).. 20-битный тег подразумевает выравнивание страниц памяти на 4Kb границу, поскольку младшие 12-бит адреса логически сбрасываются в нуль. Чтобы скоростной кэш не превратился в тормознутый флоп, при помощи аппаратного бит-теста поиск осуществляется одновременно во-всех 512-ти тегах буквально за 1 такт. Только в случае попадания в тег, контроллёр снимает с адреса индексную часть и приступает к проверке всех кэш-строк в данном банке Way, иначе запрос перенаправляется кэшу сл.уровня. Очередным кэшам приходится уже туговато, у них теги меньшей разрядности, а значит им предстоит иметь дело уже не с страницами, а с сегментами - соответственно перебирать приходится уже больше индексов в банке(Way). Например 16-битный тег кэша(L2) очищает младшие 16-бит адреса, что вынуждает кэш работать уже с блоками, размером 64Kb. Блоки 8-метрового кэша(L3) выравниваются вообще на пол-метра, поэтому их индексация занимает больше времени. Младшие 6-бит адреса в поиске не принимают участия - в случае кэш-попадания, по их содержимому выбирается конкретный байт из Cache-Line. Передача запроса на уровень ниже (L1->L2->L3->Mem) может осуществляться двумя способами. В первом случае, запрос отправляется сразу всем оппонентам одновременно - это т.н. широковещательный запрос 'Look-Aside'. Если выстрел попал в L1, то запросы к остальным снимаются - в этом случае говорят о кэш-попадании (Cache-Hit). Если-же случился промах (Cache-Miss), то запросы к L2-3 снимаются поочерёдно, пока запрос не достигнет памяти ОЗУ. Вариант хороший, только съедает много энергии. Альтернативой ему служит вариант 'Look-Through', когда обращения начинаются только после фиксации кэш-промахов. При этом теряется всего 1-такт, зато экономится энергия. Оранизация кэш В природе мирно сосуществуют 3 способа отображения памяти в кэш: кэш прямого отображения 'Direct-Mapped', полностью ассоциативный кэш 'Fully-associative', и их комбинация - наборно-ассоциативный кэш 'Set-associative'. Сейчас на всех уровнях применяется только 'Set-Cache', поэтому не будем забивать себе мозги, а рассмотрим только его. В архитектуре 'Set-associative', все строки каждого из банков(Way) делятся на несколько наборов(Set). Если в банке имеем 64-строки, то их можно условно поделить на 2-набора, по 32-строки в каждом: Когда такой кэш отображает в себе память, он будет пытаться поместить первые 32-строки каждой из страниц, только в свой набор Set(0). Для следующих 32-х строк страницы-памяти, отводится уже место в наборе Set(1) и т.д. То-есть строка(20) любой из страниц памяти не может попасть в набор(1), а только в набор(0) - в этом и заключается ассоциативность. По мнению кэш-контроллёра, искать строки при такой организации проще, чем когда они переплетаются в непонятный клубок - ему виднее.. Однако своё мнение на этот счёт имеет не бритый 'Fully-associative cache', который беспорядочно кидает строки в любую/свободную область банков Way (кто первый, того и тапки). 'Direct-Mapped' относится к порядку уже чуть лояльней, он поддерживает нумерацию и загружает только те строки, номера которых соответствуют его номерам один-к-одному. Таким образом, рассматриваемый нами 'Set-associative cache' впитал в себя всё/лучшее своих предшественников и сдавать позиции не намерен. Политика замещения данных в кэш Ясно, что организация кэш требует смотрящего, который с высока следил-бы за порядком и препятствовал случайной перезаписи уже хранящиеся в кэш данных. Контроль осуществляется посредством 4-х бит, два из которых являются значимыми - бит(М) 'Modified cache-line', и бит(V) сигнализирующего, что кэш-строка занята и кому-то принадлежит 'Valid cache-line'. Эти биты добавляются старшими в тегах кэш-строки. Бит-модификации даёт контроллёру знать, нужно-ли перезаписывать в ОЗУ строку перед выгрузкой её из кэш-памяти. Такая дилема возникает у него только в двух случаях: (1)когда процессор встречает инструкцию очистки кэша с выгрузкой строк WBINVD - Write-Back Invalidate cache, (2)при обычных обстоятельствах для поддерки когерентности кэш с оперативной памятью (остальные ситуации вытекают из этих/двух). В свою очерель бит-валидности указывает на то, что на данный момент кэш-строка действительно отображает соответствующую строку памяти, и её нежелательно выталкивать или перезаписывать новой строкой.Размеры кэша и ОЗУ сильно отличаются, поэтому неизбежно наступает момент, когда придётся освободить одну из кэш-строк, чтобы загрузить на её место новую. Алгоритмы замещения стары как-мир и плавают на трёх китах: случайный RANDOM - орёл или решка, FIFO - становимся в очередь, и LRU - редко используемая строка. Первый неэффективен, зато прост в реализации. Второй - более надёжный, но оставляет желать лучшего. Третий - требовательный к ресурсам, зато наиболее результативный - его и применяют в современной кэш-памяти. Биты V/M были введены в тег специально для поддержки работы алгоритма LRU. Поддержка когерентности Бывают ситуации, когда программа работает с внешним устройством, и это устройство ждёт каких-либо данных от программы. Процессор грузит исполняемый код в свой кэш, подготавливает данные, после чего сообщает девайсу, что запрос готов. Устройство обращается к памяти и... данных там не находит. Почему? Всё просто - данные-то есть, только остались они в кэш-памяти, и ЦП не побеспокоился о своевременной выгрузки их в ОЗУ. Такая ситуация носит проблемный характер, а её решение назвали "Поддержкой когерентности". В идеальном случае, отмеченные битом(М) изменнёные кэш-строки нужно выгружать в ОЗУ сразу после их модификации. Тогда проблем с когерентностью не будет, зато возникнет другая проблема - жуткие тормоза, поскольку процесс требует записи в неуклюжую память. Если программе приспичит менять данные через короткие промежутки времени, тогда ЦП только и будет делать, что записывать данные в ОЗУ, а мы сможем высушить вёсла за это время. Значит такой подход для кэша не преемлен - решать проблемы когерентности выпало на плечи двух политик записи в ОЗУ: Write-Through - подразумевает сквозную записью модифицированных кэш-строк. С данной политикой солидарен кэш(L1). Как только строка получает бит(М), она сразу копируется в кэш(L2) - задумчивость тут не прощается. L1 снимает с себя обязанность по разбору грязных строк, и озадачивает этим кэши следующих уровней. Write-Back - альтернатива первой. Она придерживается правил отложенной записи (М)строк. Для их хранения, современный кэш-контроллёр имеет не один, а целых четыре "буфера отложеной записи", организованых по-принципу FIFO - первым пришёл, первым выйдешь. Когда при записи возникает попадание в кэш, эти буферы сразу обновляются. Контроллёр ждёт освобождения шины-памяти (её могут занять устройства c DMA), и при первой-же возможности информирует об этом ЦП. Только теперь тот уверен, что шина свободна и можно воспользоваться ею для циклов записи модифицированных строк в основную память. Ознакомится с текущими политиками можно запросив отчёт у 'PC-Wizard'. Нужно сказать, что ни каждый софт их показывает, но если кого заинтересует, то вот: Код
>> Процессор Type : Intel Celeron D 336J, сокет 775 Кодовое имя : Prescott > Data Cache L1 : 16 Кб, 8-way set-associative, 64-byte line Режим записи : Write-Through Number of Sets : 32 > Кэшe L2 : 256 Кб, 4-way set-associative, 64-byte line Режим записи : Write-Back Number of Sets : 512 Некэшируемые регионы памяти Нужно сказать, что не всякую область памяти можно кэшировать. Есть участки, которые и силком не загонишь в кэш - для них кэширование принципиально недопустимо. К таким участкам можно отнести, например разделяемую память адаптеров. Если кэшировать такие области, то обязательно всплывает наружу проблема когерентности кэш. Кроме того, кэширование полезно отключать при выполнении однократно исполняемых участков программы (например, инициализации) с тем, чтобы из кэша не вытеснялись более полезные фрагменты кода. Когда процессор натыкается на некэшируемый регион памяти, все обращения R/W перенаправляются сразу на системную шину. Такой тип требуется для ввода-вывода посредством MMIO (Memory Mapped I/O). В противоположность к этому, в кэш имеются и страницы, которые вообще не выгружаются из него, разве-что принудительно не очистить кэш инструкцией INVD (очистка без сброса М-строк в память). К таким регионам можно отнести системные страницы гипервизора, часто используемые библиотеки и прочии. Невыгружаемые пулы положительно сказываеются на производительности системы в общем.Регионы и методы кэширования зависят от возможностей конкретного ЦП. Как-правило программируются они через набор его регистров 'MTRRs - Memory Type Range Registers' (регистры свойств областей памяти), или внутри таблицы 'PAT - Page Attribute Table' (таблица атрибутов страниц памяти): Буфер странслированных адресов TLB Ещё одной разновидностью кэш-памяти является ассоциативный буфер TLB - Translation Lookaside Buffer. Этот кэш-буфер во многом похож на кэши(L1.2.3), за исключением одной поправки - в нём нет места для данных. Кэш предназначен для хранения только адресов последних затребованных страниц виртуальной памяти. Если транслятор страниц отключен в блоке MMU процессора, то TLB так-же отключается. Прозрачен он и в реальном режиме. Имеются три раздельных буфера TLB для хранения адресов 4K,2M и 4M-байтных страниц соответственно. Средняя ёмкость - 64 индекса для 4-Кбайтных страниц, что позволяет мгновенно сформировать физический адрес только для 256Kb основной памяти (64х4). При этом по статистике, вероятность кэш-попаданий в TLB составляет 98%, т.е. только в 2-х случаях из 100 будут промахи: Сути в том, что на трансляцию адреса виртуальной страницы уходит много времени. Сначала нужно опросить регистр(CR3), чтобы определиться с базой каталога страниц(PDT); потом просканировать каталог страниц(PT); ..и наконец в таблице(РТ) найти запись(PTE). Такой караван проверок отрицательно сказывается на производительности системы, поэтому использовав адрес страницы один раз, процессор запоминает его в страничном кэше TLB. В следующий раз, когда процессору потребуется страница, он опрашивает и таблицу и кэш одновременно, и если происходит кэш-попадание, то получаем прирост скорости за счёт обхода этапа трансляции - адрес уже готовый. Кому всё побарабану - так это 12-битному оффсету, которому в этом театре-действий выпало играть роль массовки - поле предназначено для выбора смещения внутри найденной/4-Кбайтной страницы памяти. --------------------------------------------------- Задраиваем люки.. Считаю, что для одной темы букаф напечатано уже предостаточно, и пора прекращать сие повествование. Если найдутся неточности, то буду рад услышать разумное их опровержение. В подборе и оформлении материала принимали участие: 0. Google 1. Intel Software Manual volume 1,2,3 2. Встроеные средства WinXP 3. Программы сбора информации: PC-Wizard, Dr.Hardware, HWiNFO-32 4. НЕХ-редакторы: WinHEX, HxD, Hiew 5. Редакторы: Word, Exel, Photoshop, EditPlus 6. Горячительные напитки - по вкусу..
10
|
0 / 0 / 0
Регистрация: 29.11.2021
Сообщений: 2
|
|
29.11.2021, 22:42 | 14 |
Возник вопрос - если записывать по непрерывным физическим адресам данные объемом 4 Мб (для примера) на новых процессорах интел (skylake и новее, до coffee lake), то контроллер памяти все равно будет писать первые 64 байта на планку в первом канале, а вторые 64 байта на планку во втором канале? Будет просто писать не непрерывно?
Ведь за смену канала у скайлейка и новее отвечают биты, начиная только с 8-го.
0
|
Эксперт Hardware
|
|
30.11.2021, 17:42 [ТС] | 15 |
Это смотря в каком режиме работает контролёр.
Если две ОЗУ одинакового размера, то получаем реально 2-канальный режим. В этом случае, первые 64-байта попадут в первую ОЗУ, а вторые во-второю. Если-же планки разного размера (например 4 и 2), то контролёр переключается в режим Flex, когда в 2-канальном режиме оказываются две 2-гиговые области, а вторая половина 4-гиговой уходит во Flex и контролёр переключается в 1-канал. Поэтому здесь имеет значение, в какую область памяти попадут у вас "непрерывные физ.адреса объёмом 4МБ". Код
________ | | | FLEX | | 2 GB | |________| ________ | | | | | 2 GB |<-- 2 chanel -->| 2 GB | | | | | |________| |________|
0
|
0 / 0 / 0
Регистрация: 29.11.2021
Сообщений: 2
|
|
30.11.2021, 18:11 | 16 |
Понятно, что планки одинакового размера.
И я понимаю, что первые 64 байта попадут в первую планку, а вторые - во вторую. Вопрос в другом. Контроллер памяти каким образом переключается с непрерывной записи по адресам на прерывную? Как он знает, что после записи первых 64 байт ему надо писать по совсем другому адресу следующие 64 байта. Для примера. Первые 64 байта ушли по адресу 8000000h Тогда вторые 64 байта должны писаться уже по адресу 8000100h Контроллер откуда знает, что ему нужно изменить бит, отвечающий за выбор канала?
0
|
ФедосеевПавел
|
30.11.2021, 20:21
#17
|
Не по теме: R71MT, перенести эти сообщения в отдельную тему?
0
|
99 / 70 / 13
Регистрация: 15.12.2013
Сообщений: 463
|
|
17.08.2022, 12:09 | 18 |
А что случилось с изображениями, вставленными в посты?
0
|
Модератор
|
|
17.08.2022, 12:54 | 19 |
ASCII, какие конкретно?
0
|
99 / 70 / 13
Регистрация: 15.12.2013
Сообщений: 463
|
|
17.08.2022, 13:05 | 20 |
Я что, один их вижу?
0
|
17.08.2022, 13:05 | |
17.08.2022, 13:05 | |
Помогаю со студенческими работами здесь
20
Процессы и память компьютера Ввод матрицы в память компьютера Виртуальная память компьютера GlobalMemoryStatusEx Постоянно исчезает память с компьютера Как увеличить свободную память компьютера? Какой объем имеет оперативная память компьютера Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |