Что такое карта адресного пространства
Карта памяти. Критерии и способы распределения адресного пространства
Карта памяти вычислительной системы – это графическое представление распределения адресного пространства системы, разбиение таблицы доступных адресов по функциональным и программно-аппаратным признакам.
При построении микропроцессорных устройств важнейшими задачами проектировщика являются распределение адресного пространства системы; определение и распределение доступных системных адресов между ОЗУ, ПЗУ и ВУ; формирование протоколов предоставления адреса и оптимизация аппаратно-программной части обмена адресом.
В первых моделях микропроцессоров использовалось линейное распределение адресного пространства, при котором все доступное адресное пространство системы разбивалось по линейному принципу. В младших адресах располагались системные векторы прерываний, а прочая память делилась по принципу фон Неймана, отображая адреса программ и данных в единое адресное пространство системы, при этом выделялись адреса внешних устройств. С момента разработки процессора I8086 и по настоящее время применяется принцип сегментированного разбиения,при котором область программ и данных разбивается на несколько сегментов (страниц) по функциональным признакам. Так, в микропроцессорной системе, организованной на базе МП I8086, присутствуют четыре сегмента (кода, данных, стековый и дополнительный).
Позднее при увеличении доступного адресного пространства появились более сложные, но вместе с тем и более эффективные способы организации системной памяти. Так, начиная с процессора I80286, принят принцип дескрипторной адресации, при котором сегменты в памяти адресуются посредством дескрипторов – специальных таблиц в памяти, отвечающих за распределение и доступ к адресам системы.
Основными критериями распределения адресного пространства системы являются:
• максимально доступное адресное пространство; • минимум аппаратных затрат на реализацию необходимых системных функций;
• максимальное быстродействие системной памяти в сочетании с контролем достоверности информации;
• обеспечение выбранной модели памяти необходимыми системными программными и аппаратными ресурсами;
• удобочитаемость карты распределения, подразумевающая иерархический, сегментированный или иной способ описания адресного пространства, при котором разработчик достаточно легко проводит анализ адресов аппаратной части системы;
• наращиваемость, возможность комбинационного проектирования адресного пространства.
Вышеперечисленные требования не отражают всех возможных критериев и задач распределения адресного пространства, которые могут возникнуть в процессе разработки микропроцессорной системы, но являются одними из основных.
Контрольные вопросы к главе 1
1. Дайте определение понятиям «автомат», «программа», «команда» и «память программ».
2. Приведите основные исторические сведения о развитии микропроцессоров.
3. Перечислите критерии классификации микропроцессоров.
4. Перечислите компоненты простейшей микропроцессорной системы, организованной по архитектуре «с тремя шинами».
5. Каковы основные принципы построения MPP- и SMP-систем?
6. Приведите общий алгоритм выполнения команды процессором.
7. Дайте определение понятиям «системная синхронизация», «машинный такт», «машинный цикл» и «цикл команды».
8. Каковы алгоритмы функционирования микропроцессорной системы в режиме прерывания и прямого доступа к памяти?
9. Приведите основные характеристики запоминающих устройств.
10. Каковы принципы функционирования динамической, статической и энергонезависимой памяти? Назовите методы и способы организации кэшпамяти.
11. Что такое карта памяти? Перечислите основные критерии и способы распределения адресного пространства вычислительных систем.
Дата добавления: 2016-10-17 ; просмотров: 1320 ; ЗАКАЗАТЬ НАПИСАНИЕ РАБОТЫ
Организация памяти процесса
Управление памятью – центральный аспект в работе операционных систем. Он оказывает основополагающее влияние на сферу программирования и системного администрирования. В нескольких последующих постах я коснусь вопросов, связанных с работой памяти. Упор будет сделан на практические аспекты, однако и детали внутреннего устройства игнорировать не будем. Рассматриваемые концепции являются достаточно общими, но проиллюстрированы в основном на примере Linux и Windows, выполняющихся на x86-32 компьютере. Первый пост описывает организацию памяти пользовательских процессов.
Каждый процесс в многозадачной ОС выполняется в собственной “песочнице”. Эта песочница представляет собой виртуальное адресное пространство, которое в 32-битном защищенном режиме всегда имеет размер равный 4 гигабайтам. Соответствие между виртуальным пространством и физической памятью описывается с помощью таблицы страниц (page table). Ядро создает и заполняет таблицы, а процессор обращается к ним при необходимости осуществить трансляцию адреса. Каждый процесс работает со своим набором таблиц. Есть один важный момент — концепция виртуальной адресации распространяется на все выполняемое ПО, включая и само ядро. По этой причине для него резервируется часть виртуального адресного пространства (т.н. kernel space).
Это конечно не значит, что ядро занимает все это пространство, просто данный диапазон адресов может быть использован для мэппирования любой части физического адресного пространства по выбору ядра. Страницы памяти, соответствующие kernel space, помечены в таблицах страниц как доступные исключительно для привилегированного кода (кольцо 2 или более привилегированное). При попытке обращения к этим страницам из user mode кода генерируется page fault. В случае с Linux, kernel space всегда присутствует в памяти процесса, и разные процессы мэппируют kernel space в одну и ту же область физической памяти. Таким образом, код и данные ядра всегда доступны при необходимости обработать прерывание или системный вызов. В противоположность, оперативная память, замэппированная в user mode space, меняется при каждом переключении контекста.
Синим цветом на рисунке отмечены области виртуального адресного пространства, которым в соответствие поставлены участки физической памяти; белым цветом — еще не использованные области. Как видно, Firefox использовал большую часть своего виртуального адресного пространства. Все мы знаем о легендарной прожорливости этой программы в отношении оперативной памяти. Синие полосы на рисунке — это сегменты памяти программы, такие как куча (heap), стек и так далее. Обратите внимание, что в данном случае под сегментами мы подразумеваем просто непрерывные адресные диапазоны. Это не те сегменты, о которых мы говорим при описании сегментации в Intel процессорах. Так или иначе, вот стандартная схема организации памяти процесса в Linux:
Давным давно, когда компьютерная техника находилась в совсем еще младенческом возрасте, начальные виртуальные адреса сегментов были совершенно одинаковыми почти для всех процессов, выполняемых машиной. Из-за этого значительно упрощалось удаленное эксплуатирование уязвимостей. Эксплойту часто необходимо обращаться к памяти по абсолютным адресам, например по некоторому адресу в стеке, по адресу библиотечной функции, и тому подобное. Хакер, рассчитывающий осуществить удаленную атаку, должен выбирать адреса для обращения в слепую в расчете на то, что размещение сегментов программы в памяти на разных машинах будет идентичным. И когда оно действительно идентичное, случается, что людей хакают. По этой причине, приобрел популярность механизм рандомизации расположения сегментов в адресном пространстве процесса. Linux рандомизирует расположение стека, сегмента для memory mapping, и кучи – их стартовый адрес вычисляется путем добавления смещения. К сожалению, 32-битное пространство не очень-то большое, и эффективность рандомизации в известной степени нивелируется.
В верхней части user mode space расположен стековый сегмент. Большинство языков программирования используют его для хранения локальных переменных и аргументов, переданных в функцию. Вызов функции или метода приводит к помещению в стек т.н. стекового фрейма. Когда функция возвращает управление, стековый фрейм уничтожается. Стек устроен достаточно просто — данные обрабатываются в соответствии с принципом «последним пришёл — первым обслужен» (LIFO). По этой причине, для отслеживания содержания стека не нужно сложных управляющих структур – достаточно всего лишь указателя на верхушку стека. Добавление данных в стек и их удаление – быстрая и четко определенная операция. Более того, многократное использование одних и тех же областей стекового сегмента приводит к тому, что они, как правило, находятся в кеше процессора, что еще более ускоряет доступ. Каждый тред в рамках процесса работает с собственным стеком.
Возможна ситуация, когда пространство, отведенное под стековый сегмент, не может вместить в себя добавляемые данные. В результате, будет сгенерирован page fault, который в Linux обрабатывается функцией expand_stack(). Она, в свою очередь, вызовет другую функцию — acct_stack_growth(), которая отвечает за проверку возможности увеличить стековый сегмент. Если размер стекового сегмента меньше значения константы RLIMIT_STACK (обычно 8 МБ), то он наращивается, и программа продолжает выполняться как ни в чем не бывало. Это стандартный механизм, посредством которого размер стекового сегмента увеличивается в соответствии с потребностями. Однако, если достигнут максимально разрещённый размер стекового сегмента, то происходит переполнение стека (stack overflow), и программе посылается сигнал Segmentation Fault. Стековый сегмент может увеличиваться при необходимости, но никогда не уменьшается, даже если сама стековая структура, содержащаяся в нем, становиться меньше. Подобно федеральному бюджету, стековый сегмент может только расти.
Динамическое наращивание стека – единственная ситуация, когда обращение к «немэппированной» области памяти, может быть расценено как валидная операция. Любое другое обращение приводит к генерации page fault, за которым следует Segmentation Fault. Некоторые используемые области помечены как read-only, и обращение к ним также приводит к Segmentation Fault.
Под стеком располагается сегмент для memory mapping. Ядро использует этот сегмент для мэппирования (отображания в память) содержимого файлов. Любое приложение может воспользоваться данным функционалом посредством системного вызовома mmap() (ссылка на описание реализации вызова mmap) или CreateFileMapping() / MapViewOfFile() в Windows. Отображение файлов в память – удобный и высокопроизводительный метод файлового ввода / вывода, и он используется, например, для загрузки динамических библиотек. Существует возможность осуществить анонимное отображение в память (anonymous memory mapping), в результате чего получим область, в которую не отображен никакой файл, и которая вместо этого используется для размещения разного рода данных, с которыми работает программа. Если в Linux запросить выделение большого блока памяти с помощью malloc(), то вместо того, чтобы выделить память в куче, стандартная библиотека C задействует механизм анонимного отображения. Слово «большой», в данном случае, означает величину в байтах большую, чем значение константы MMAP_THRESHOLD. По умолчанию, это величина равна 128 кБ, и может контролироваться через вызов mallopt().
Кстати о куче. Она идет следующей в нашем описании адресного пространства процесса. Подобно стеку, куча используется для выделения памяти во время выполнения программы. В отличие от стека, память, выделенная в куче, сохранится после того, как функция, вызвавшая выделение этой памяти, завершится. Большинство языков предоставляют средства управления памятью в куче. Таким образом, ядро и среда выполнения языка совместно осуществляют динамическое выделение дополнительной памяти. В языке C, интерфейсом для работы с кучей является семейство функций malloc(), в то время как в языках с поддержкой garbage collection, вроде C#, основной интерфейс – это оператор new.
Если текущий размер кучи позволяет выделить запрошенный объем памяти, то выделение может быть осуществлено средствами одной лишь среды выполнения, без привлечения ядра. В противном случае, функция malloc() задействует системный вызов brk() для необходимого увеличения кучи (ссылка на описание реализации вызова brk). Управление памятью в куче – нетривиальная задача, для решения которой используются сложные алгоритмы. Данные алгоритмы стремятся достичь высокой скорости и эффективности в условиях непредсказуемых и хаотичных пэттернов выделения памяти в наших программах. Время, затрачиваемое на каждый запрос по выделению памяти в куче, может разительно отличаться. Для решения данной проблемы, системы реального времени используют специализированные аллокаторы памяти. Куча также подвержена фрагментированию, что, к примеру, изображено на рисунке:
Наконец, мы добрались до сегментов, расположенных в нижней части адресного пространства процесса: BSS, сегмент данных (data segment) и сегмент кода (text segment). BSS и data сегмент хранят данные, соответствующий static переменным в исходном коде на C. Разница в том, что в BSS хранятся данные, соответствующие неинициализированным переменным, чьи значения явно не указаны в исходном коде (в действительности, там хранятся объекты, при создании которых в декларации переменной либо явно указано нулевое значение, либо значение изначально не указано, и в линкуемых файлах нет таких же common символов, с ненулевым значением. – прим. перевод.). Для сегмента BSS используется анонимное отображение в память, т.е. никакой файл в этот сегмент не мэппируется. Если в исходном файле на C использовать int cntActiveUsers, то место под соответствующий объект будет выделено в BSS.
В отличии от BSS, data cегмент хранит объекты, которым в исходном коде соответствуют декларации static переменных, инициализированных ненулевым значением. Этот сегмент памяти не является анонимным — в него мэппируется часть образа программы. Таким образом, если мы используем static int cntWorkerBees = 10, то место под соответствующий объект будет выделено в data сегменте, и оно будет хранить значение 10. Хотя в data сегмент отображается файл, это т.н. «приватный мэппинг» (private memory mapping). Это значит, что изменения данных в этом сегменте не повлияют на содержание соответствующего файла. Так и должно быть, иначе присвоения значений глобальным переменным привели бы к изменению содержания файла, хранящегося на диске. В данном случае это совсем не нужно!
Мы можем посмотреть, как используются области памяти процесса, прочитав содержимое файла /proc/pid_of_process/maps. Обратите внимание, что содержимое самого сегмента может состоять из различных областей. Например, каждой мэппируемой в memory mapping сегмент динамической библиотеке отводится своя область, и в ней можно выделить области для BSS и data сегментов библиотеки. В следующем посте поясним, что конкретно подразумевается под словом “область”. Учтите, что иногда люди говорят “data сегмент”, подразумевая под этим data + BSS + heap.
Можно использовать утилиты nm и objdump для просмотра содержимого бинарных исполняемых образов: символов, их адресов, сегментов и т.д. Наконец, то, что описано в этом посте – это так называемая “гибкая” организация памяти процесса (flexible memory layout), которая вот уже несколько лет используется в Linux по умолчанию. Данная схема предполагает, что у нас определено значение константы RLIMIT_STACK. Когда это не так, Linux использует т.н. классическую организации, которая изображена на рисунке:
Ну вот и все. На этом наш разговор об организации памяти процесса завершен. В следующем посте рассмотрим как ядро отслеживает размеры описанных областей памяти. Также коснемся вопроса мэппирования, какое отношение к этому имеет чтение и запись файлов, и что означают цифры, описывающие использование памяти.
Сегментация памяти (Схема памяти компьютера)
Представляю, Вам, перевод статьи одного из разработчиков PHP, в том числе версии 7 и выше, сертифицированного инженера ZendFramework. В данный момент работает в SensioLabs и большую часть занимается низкоуровневыми вещами, в том числе программированием в С под Unix. Оригинал статьи здесь.
Ошибка Сегментации: (Компьютерная верстка памяти)
Несколько слов, о чем эта запись в блоге
Я планирую в будущем писать технические статьи о PHP, связанные с глубоким пониманием памяти. Мне нужно, чтобы мои читатели имели такие знания, которые им помогут понять некоторые концепции дальнейшего объяснения. Для того, чтобы ответить на этот вопрос, нам придется перемотать время назад в 1960-е года. Я собираюсь объяснить вам, как работает компьютер, а точнее, как происходит доступ к памяти в современном компьютере, а затем вы поймете, из-за чего происходит это странное сообщение об ошибке — Segmentation Fault.
То, что вы будете читать здесь, краткое изложение основ дизайна компьютерной архитектуры. Я не буду заходить слишком далеко, если это не нужно, и буду использовать хорошо известные формулировки, так что, кто работает с компьютером каждый день может понять такие важные понятия о том, как работает ПК. Существует много книг о компьютерной архитектуре. Если вы хотите углубиться дальше в этой теме, я предлагаю вам достать некоторые из них и начать читать. Кроме того, откройте исходный код ядра ОС и изучите его, будь то ядро Linux, или любое другое.
Немного истории computer science
Русские Блоги
Понимание адресного пространства процесса и пространства виртуальной памяти
Понимание адресного пространства процесса и пространства виртуальной памяти
Прежде чем перейти к теме, давайте поговорим о процессе разработки механизма управления памятью в операционной системе. Понимание этого поможет нам лучше понять механизм управления памятью в текущей операционной системе.
Один Механизм раннего распределения памяти
В ранних компьютерах для запуска программы все эти программы загружались в память, и программа запускалась непосредственно в памяти, то есть адреса памяти, к которым осуществлялся доступ в программе, были фактическими адресами физической памяти. Когда компьютер запускает несколько программ одновременно, необходимо убедиться, что общий объем памяти, используемый этими программами, меньше, чем фактическая физическая память компьютера. Когда программа запускает несколько программ одновременно, как операционная система распределяет память для этих программ? Следующие примеры иллюстрируют метод распределения памяти в то время:
Рисунок 1 Метод раннего распределения памяти
Проблема 1. Адресное пространство процесса не изолировано. Поскольку программы напрямую обращаются к физической памяти, вредоносные программы могут изменять данные памяти других процессов по своему желанию для достижения цели уничтожения. Некоторые программы, которые не являются вредоносными, но имеют ошибки, могут случайно изменить данные памяти других программ, что приведет к ненормальной работе других программ. Эта ситуация невыносима для пользователя, потому что, когда пользователь хочет использовать компьютер, одна из задач не выполняется, по крайней мере, это не может повлиять на другие задачи.
Проблема 2: низкая эффективность использования памяти. Когда работают и A, и B, если пользователь снова запускает программу C, а программе C требуется 20 МБ памяти для запуска, и в это время в системе доступно только 8 МБ свободного места, поэтому система должна быть в Выберите одну из запущенных программ, чтобы временно скопировать данные программы на жесткий диск, освободить часть пространства для использования программой C, а затем загрузить все данные программы C в память для запуска. Вполне возможно, что в этом процессе загружается и выгружается большой объем данных, что приводит к очень низкой эффективности.
Два Сегментированный
Чтобы решить вышеупомянутые проблемы, люди придумали обходной путь, который заключается в добавлении промежуточного уровня и использовании метода косвенного адресного доступа для доступа к физической памяти. Согласно этому методу адрес памяти, к которому осуществляется доступ в программе, больше не является фактическим адресом физической памяти, а является виртуальным адресом, а затем операционная система отображает этот виртуальный адрес на соответствующий адрес физической памяти. Таким образом, пока операционная система обрабатывает сопоставление виртуальных адресов с адресами физической памяти, она может гарантировать, что адреса памяти, к которым в конечном итоге обращаются различные программы, расположены в разных областях, не перекрывая друг друга, и может быть достигнут эффект изоляции адресного пространства памяти.
При создании процесса операционная система выделяет для процесса размер 4 ГБ. виртуальный Адресное пространство процесса. Причина, по которой это 4 ГБ, заключается в том, что в 32-разрядной операционной системе указатель имеет длину 4 байта, а адресная способность 4-байтового указателя составляет от 0x00000000 до 0xFFFFFFFF, а максимальное значение 0xFFFFFFFF представляет емкость 4 ГБ. В отличие от виртуального адресного пространства существует также физическое адресное пространство, которое соответствует реальной физической памяти. Если на вашем компьютере установлено 512 МБ памяти, диапазон этого физического адресного пространства составляет 0x00000000
0x1FFFFFFF. Когда операционная система сопоставляет виртуальный адрес с физическим адресом, он может сопоставить только этот диапазон, а операционная система может сопоставить только этот диапазон. При создании процессов каждый процесс будет иметь собственное виртуальное адресное пространство размером 4 ГБ. Следует отметить, что это адресное пространство размером 4 ГБ является «виртуальным», а не реальным, и каждый процесс может получать доступ к данным только в своем собственном виртуальном адресном пространстве и не может получать доступ к данным в других процессах. Это достигается этим методом. Устраните изоляцию между процессами. Свободны ли эти 4 ГБ приложений виртуального адресного пространства? К сожалению, в системе Windows это виртуальное адресное пространство разделено на 4 части: область нулевого указателя, пользовательская область, запрещенная область 64 КБ и область ядра. Приложение может использовать только пользовательскую область, которая составляет около 2 ГБ (можно настроить до 3 ГБ). Область ядра составляет 2 ГБ. Область ядра сохраняет планирование системных потоков, управление памятью, драйверы устройств и другие данные. Эта часть данных используется всеми процессами, но приложения не могут получить к ней прямой доступ.
Причина, по которой люди создают виртуальное адресное пространство, состоит в том, чтобы решить проблему изоляции адресного пространства процесса. Однако, если программа хочет выполняться, она должна выполняться в реальной памяти, поэтому между виртуальным адресом и физическим адресом должна быть установлена связь. Таким образом, через механизм отображения, когда программа обращается к значению адреса в виртуальном адресном пространстве, это эквивалентно доступу к другому значению в физическом адресном пространстве. Люди думают о Сегментированный (Sagmentation), его идея состоит в том, чтобы сделать однозначное сопоставление между виртуальным адресным пространством и физическим адресным пространством. Например, пространство 10 МБ в виртуальном адресном пространстве отображается на пространство 10 МБ в физическом адресном пространстве. Эту идею нетрудно понять. Операционная система гарантирует, что адресное пространство различных процессов отображается в разные области физического адресного пространства, так что каждый процесс, наконец, обращается к
Метод отображения памяти.
Рисунок 2 Метод сопоставления сегментированной памяти
Хотя этот метод сегментированного отображения решает первую и третью проблемы, упомянутые выше, он не решает вторую проблему, то есть эффективность использования памяти. В методе сегментированного отображения вся программа каждый раз переключается в память и выгружается из нее, что приводит к большому количеству операций доступа к диску, что приводит к низкой эффективности. Поэтому этот метод сопоставления все еще немного груб, а степень детализации относительно велика. Фактически, работа программы имеет характеристики локальности. В определенный период времени программа получает доступ только к небольшой части данных программы, то есть большая часть данных программы не будет использоваться в течение определенного периода времени. Исходя из этой ситуации, люди думают о методе сегментации памяти и отображения с меньшей степенью детализации. Этот метод является Пагинация (Paging) 。
три Пагинация
В методе сегментации программа всегда загружается в память при каждом запуске программы, но метод разбиения на страницы отличается. Идея разбиения на страницы состоит в том, чтобы выделить память, для которой страница используется во время работы программы, а неиспользуемые страницы временно хранятся на жестком диске. Когда эти страницы используются, для этих страниц выделяется память в физическом адресном пространстве, а затем устанавливается отображение между страницами в виртуальном адресном пространстве и вновь выделенной страницей физической памяти.
После создания структуры данных, необходимой для виртуального адресного пространства, процесс начинает читать первую страницу PE-файла. Первая страница PE-файла содержит такую информацию, как заголовок PE-файла и таблица сегментов. В соответствии с заголовком файла и таблицей сегментов процесс сопоставляет все сегменты PE-файла с соответствующими страницами в виртуальном адресном пространстве (в PE-файле). Длина сегмента кратна длине страницы). В настоящее время реальные инструкции и данные PE-файла не загружены в память.Операционная система просто устанавливает взаимосвязь между PE-файлом и страницей в виртуальном адресном пространстве процесса на основе заголовка PE-файла и другой информации. Когда ЦП хочет получить доступ к определенному виртуальному адресу, используемому в программе, когда ЦП обнаруживает, что с адресом не связан физический адрес, ЦП думает, что страница, на которой расположен виртуальный адрес, является пустой страницей, а ЦП считает, что это ошибка страницы ( Page Fault), ЦП также знает, что операционная система не выделила память для PE-страницы, и ЦП вернет управление операционной системе. Затем операционная система выделяет страницу в физическом пространстве для PE-страницы, а затем сопоставляет физическую страницу с виртуальной страницей в виртуальном пространстве, а затем возвращает управление процессу, и процесс перезапускается с позиции, где только что произошла ошибка страницы. выполненный. Поскольку в это время для этой страницы PE-файла выделена память, сбой страницы не произойдет. При выполнении программы сбои страниц будут продолжать возникать, и операционная система также будет выделять соответствующие физические страницы для процесса, чтобы удовлетворить потребности процесса.
Основная идея метода разбиения на страницы заключается в том, что когда исполняемый файл выполняется на x-й странице, для x-й страницы выделяется страница памяти y, а затем эта страница памяти добавляется в таблицу сопоставления виртуального адресного пространства процесса. Эта таблица сопоставления эквивалентна В функции y = f (x). Приложение может получить доступ к странице y, связанной со страницей x, через эту таблицу сопоставления.
подводить итоги: