Comments 27
Хотелось бы услышать побольше про маппинг виртуальной памяти на физическую - как структуры ядра ОС отображаются на таблицы страниц процессора, в какие моменты происходят изменения и дорогие действия (скажем, инвалидация TLB).
Здравствуйте! В принципе с вами согласен. Можно рассказать про многоуровневые таблицы. Посмотрю, что там со временем у меня после серии публикаций.
А как вооще можно было бы описать работу виртуальной памяти без введения в эти самые "многоуровневые таблицы " и MMU (если не ошибаюсь).
У Вас получилась телега впереди лошади.
Виртуальная память связана с физической через таблицы страниц, но, прошу заметить, понимание того как они работают дадут вам ответ только на вопрос "как виртуальная память связана с физической". Если по вашей аналогии с лошадью и повозкой, то таблица страниц - это конская упряжка.
В общем, это следовало бы рассмотреть, но в частности здесь я сконцентрировал свое внимание на других деталях: как страница загружается в физическую память и при каких условиях.
Можно сказать, если по-простому говорить, что я рассмотрел это как "черную коробку", где мне важна функциональность загрузки страницы в физическую память.
Надеюсь, вы поняли мою точку зрения и почему я решил это не вводить в курс дела.
Надеюсь, вы поняли мою точку зрения и почему я решил это не вводить в курс дела.
Честно говоря нет, не понял. Я много раз читал и слушал про механизм виртуальной памяти на разных платформах, начиная с ИБМ МФ и БЭСМ-6, и всегда эти рассказы во первых же строках раскрывали смысл "черной коробочки", или DAT в случае с ИБМ МФ:
An IBM Mainframe DAT (Dynamic Address Translation) refers to the core hardware/software process that translates virtual memory addresses into physical ones, ...
На любых других платформа также имеются аналоги этому по разному работающие, но по функциональности примерно одинаковы.
В БЭСМ-6 виртуальная память устранена иначе.
Ну хоть какаято польза от подорожания памяти - пошли статьи как с ней правильно работать
В следующей серии будет рассказано про механизм управления памятью в виртуальном адресном пространстве процесса, то есть про стандартную библиотеку Glibc. Это Вызовы malloc, calloc и realloc. Если объема не хватит, сразу приведу особенности работы с физической памятью (сколько выделяется, когда и почему).
Теперь про разницу виртуальной и физической памяти.
Странное описание разницы между типами памяти. Они все физические.
Есть RAM - оперативная память, с прямой двоичной адресацией. Каждому двоичному адресу на шине процессора, прямо соответствует ячейка памяти в RAM.
Есть виртуальная память на диске, которая организована как файл в файловой системе. Нельзя просто выставить на шине процессора адрес в области виртуальной памяти, и считать содержимое. Это делается через посредника, который преобразует двоичный адрес ячейки памяти, к которой обращается приложение, в позицию элемента в файле на диске.
Сразу после аллокации (скажем, анонимным mmap'ом) кусок памяти только виртуальный - ему не соответствуют никакие данные ни в RAM ни на диске. Только после первого обращения при обработке исключения процессора будут выделяться физические страницы, которые позже могут переехать на диск.
Виртуальная память не обязана быть на диске, возможно, Вы немного неправильно поняли. Скажем, что мы выделили память каким-нибудь системным вызовом и получили указатель. Этот указатель ВСЕГДА будет указывать на адрес в виртуальном адресном пространстве, что как раз и описывается структурой mm_struct в ядре. Эта память по умолчанию не в оперативной памяти. Виртуальные страницы связываются с физическими через таблицу страниц, что в одном и комментариев выше посоветовали рассмотреть. Это означает, что такой адрес при обращении будет адресовать линейно физическую память. Про сущность виртуальных страниц могу добавить еще немного про тот факт, что если она не в памяти, то они либо никогда в нее не загружались (и при обращении случится minor page fault), либо когда-то были вытеснены на диск (и при обращении случится major page fault).
Я согласен с @LinkToOSчто описание связи виртуальной памяти с реальной (или ели хотите физической, но когда я много лет назад изучал архитектуры ЭВМ это называлось реальной памятью, хотя да в лексиконе плятформы х86 используется термин physical memory) в статье довольно запутано ("странно" у @LinkToOS. .
Вот первое что дает Гугл по поводу объяснения виртуальной памяти в ОС MVS (это понятное дело мэйнфрэйм система. Схожие описания имеются и для других платформ и ОС):
Виртуальная память — это концепция операционной системы мэйнфреймов IBM, в которой каждая задача получает собственное большое, личное адресное пространство, используя страничную организацию памяти для отображения виртуальных адресов на реальную память (ОЗУ) и диск (вспомогательное хранилище), что позволяет создавать масштабные программы, эффективно выполнять многозадачные операции и защищать память.
Ключевые концепции
Несколько адресных пространств: Вместо одной общей памяти MVS предоставляет каждой программе (задаче/заданию) собственное большое, изолированное виртуальное адресное пространство.
Отображение виртуальных адресов в реальные: Аппаратное обеспечение (блок управления памятью) преобразует виртуальные адреса, используемые программами, в физические адреса в ОЗУ или на диске с помощью таблиц страниц.
Подкачка/страничная адресация: MVS перемещает блоки памяти (страницы) между быстрым центральным хранилищем (ОЗУ) и более медленным вспомогательным хранилищем (диском) по мере необходимости, обрабатывая ошибки страничного доступа, когда программе требуется страница, отсутствующая в ОЗУ.
Аналогичное упоминает об аппартном обеспечении есть и в описании виртуальной памяти в PDP-11 (полагаю и на других платформах тоже):
MMU (Memory Management Unit): Hardware added to later PDP-11s (like the 11/70) to translate virtual addresses to physical ones, supporting segmentation and paging.
У автора отсутствует упоминание (поправьте если это не так) аппартной поддержики виртуальной памяти т.е. динамической трансляции виртуальных адресов в реальные (физические). Это важно для понимания виртуальной памяти и как она функционирует. Объяснять это через "разницу виртуальной и физической памяти"
Автор упоминает некую "таблицу страниц", но как и чем она используется не раскрывает. Нет и упоминания о сегментах имеющих место быть на х86 тоже.
Разрядность системы — это разрядность ЦПУ. Все современные ЦПУ используют 64 бита для вычислений, ....... Эти биты позволяют использовать
значений. Так как указатель — это переменная, по объему разрядности которая 64 бита, 8 байт, то и указывает она на
байт. В ОС Linux используется 48 бит для адресации в виртуальном адресном пространстве.
Инистинктивно хочется спросить: "Почему и как только 48 бит?". В статье на это ответа нет. Потому что нет описания аппаратной поддержки виртуальной памяти и роли "таблицы страниц".
Что еще важно учесть рассказывая про витуальную память это различие механизмов виртуализации памяти в Операцианных Системах и Виртуальных Машинах. Да они базуруются на одних и тех же принципах работы компьютера, но в случае ВМ это "чистая" виртуальная память от нуля до бесконечности (или до значения заданого конфигурацией ВМ), а в ОС (реальной машины или виртуальной) есть прослойка супервизора ОС, у которого процесс запрашивает память инкрементально по мере надобности, в рамках которых программа обязуется выполняться и только баг программы может обратиться во вне инкремета(ов), и только стартовый код процесса загружается в память созданой супервизором ОС. Другими словами ОС ведет учет и отслеживает все запросы прикладного процесса на память. Выход за пределы этих запросов означает аварийное завершение процесса. Гипервизор же ВМ позволяет использовать виртуальную память ВМ как угодно, полагаясь на ОС ВМ в рамках ее принципов управления процессами/программами.
В целом статья даже для меня, ИТ-шника с более чем 40 летним стажем и именно в области систем, выглядит не убедительно, малоинформативно и даже запутано. Вот примеры из статьи:
Последний важный вывод: процесс не обладает памятью. Процесс имеет виртуальное адресное пространство.
.....
Виртуальная память также выделяется страницами, как и физическая память.
Другой важный вывод заключается в выделении памяти. Виртуальная память выделяется МОМЕНТАЛЬНО при вызове. Виртуальная страница памяти будет загружена в физическую память только при первом обращении к ней.
Начал читать статью чтобы понять как работает с памятью Линукс на х86 и ничего кроме ссылок на структуры Линукс с туманными описаниями их значения и использования ядром Линукс не нашел. Нет этого в статье. При этом, хоть это и было давно, я изучал архитектуру Интел процессора и помню что там были сегменты и вообще есть четыре метода управления виртуальной памятью лишь одно из которых используется Windows и Linux. А хотелось бы узнать почему именно одно и что с остальными.
Спасибо за развернутую критику!
Да, в моей работе не рассматриваются сегменты адресного пространства процесса в деталях, однако просто упоминаются в рисунке "Адресное пространство процесса".
Относительно других тем, просто кратно поясню, что, возможно, сейчас не видны никакие результаты относительно работы с физической памятью, потому что цикл публикаций не завершен. Планируется сделать вывод "при каких условиях какие страницы в виртуальном адресном пространстве выгружаются в физическую память и какие особенности в этом плане имеет Glibc".
Я сразу понял что Вы будете в основном рассказывать как Линукс управляет памятью процессов. Но это управление в принципе может иметь место и без виртуализации памяти. И в самом деле в первых ОС процесса разделяли физическую память, и ей управлял супервизор ОС без виртуализации памяти.
Потом появились системы где виртуальная память "была" только у супервизора ОС, а процессы видели свои регионы.
В современных системах каждый процесс имеет свою виртуальную память. (Честно говоря пока не уверен что это про Линукс, но надеюсь что да)
Попытка рассказывать про все эти этапы одновременно обречена на неудачу в том смысле что неопытный читатель вряд ли такой подход поймет правильно. По идее надо описавать сначала самый низкий уровень виртуализации и восходить к уровню ОС, но можно и наоборот. В моем влучае было как раз то и наоборот, поэтому, думаю, у меня сложилось правильное понимание о том что есть основа и что есть следствие. Как говорится "богу богово, а человеку человекое".
И вообще управление памятью процессов в Линукс и виртуальная память это две практически разные (независимые) темы. Рассказывать сразу про них методически не корректно, особенно для новичков.
Вот пример как это надо было бы начинать рассказ про виртуальную память:
A Translation Lookaside Buffer (TLB) is a high-speed cache within a processor's Memory Management Unit (MMU) that stores recent translations of virtual memory addresses to physical memory addresses, acting as an address-translation cache to speed up memory access by avoiding slow page table lookups in main memory. When the CPU needs a memory location, it first checks the TLB (a TLB Hit); if found, the physical address is quickly provided, but if not (a TLB Miss), the system must consult the page tables, which is slower, requiring hardware or OS intervention. TLBs are crucial for performance, as they reduce multiple memory accesses to potentially just one, using locality of reference to cache frequently used mappings.
How it Works
Virtual to Physical: The TLB maps a Virtual Page Number (VPN) to a Physical Page Frame.
Lookup: A virtual address is broken down; the MMU uses the VPN to check the TLB.
Hit: If the translation is in the TLB, the physical address is returned instantly, saving significant time.
Miss: If not, the page table in main memory is accessed (often involving multiple memory reads), and the new translation is added to the TLB, potentially evicting an old entry.
Мне честно говоря это не очень это описание нравится потому что здесь тоже смешаны котлеты и мухи. Т.е. трансляция виртуальных адресов в физические и хранение TLB в кэше что есть тема производительности (я это выделил выше), а не принципа виртуализации памяти как такового. В итоге суть оказывается затумаененной. .
Но взял этот пример потому что он не из ИБМ мэйнфрэйм документации чтобы лишний раз не раздражать читателей неадекватно относящихся к теме ИБМ МФ. Таких здесь много.
Скажем, что мы выделили память каким-нибудь системным вызовом и получили указатель. Этот указатель ВСЕГДА будет указывать на адрес в виртуальном адресном пространстве, что как раз и описывается структурой mm_struct в ядре. Эта память по умолчанию не в оперативной памяти.
А не должне ли после этого произойти считывание кода процесса с файла на диске по этому "указателю" в физической памяти и передачи управления точке входа в процесс?
Правильно ли я понял что в этом случае под "оперативной памятью" Вы имеете в виду "физическую память"?
Под оперативной памятью понимается физическая память. По поводу считывание кода процесса с файла на диске. Нет, этот случай в принципе на рассматривается, однако понятно, что страницы с кодом загружаются как и все остальные - только при страничном прерывании.
Минуточку. Давайте всё же рассмотрим как и в чем материализуется/загружается код процесс. Вы говорите что "....страницы с кодом загружаются как и все остальные - только при страничном прерывании."
Вопрос: Что и как инициирует первоначальную загрузку кода процесса в память?
Сам процесс понятное дело сделать это не может - его еще нет. Код процесса находится в файле на диске. Система? Без оборащения к файлу с кодом процесса на диске? А ведь для того и начинается срздание адресного пространства чтобы в него поместить код из файла на диске. Причем не из файла страничного обмену куда попадают страницы процессов в результате вытеснения.
Поправьте или продолжите эту мою логику.
Вы уверены что это так и происходит на уровне машинных команд процессора что команда опрерирует данными в файле вытесненных страниц без предварительного считывания страниц в физическую память?
Ах да, Вы говорите "через посредника". Что это за такой замечательный посредник?
Посредник - это менеджер памяти.
в физическую память
Все-таки в оперативную память. Дисковая подсистема памяти тоже физическая. Любая память физическая. А разделение на "физические" и "виртуальные" относится к адресам.
команда оперирует данными в файле вытесненных страниц без предварительного считывания страниц в физическую память
Запись на дисках по блокам. Поэтому без кеша в оперативной памяти обойтись не получится.
Хотя теоретически, можно было бы сделать аппаратную поддержку, вовлечь контролер диска в процедуру отображения, и резервировать на диске место в специальном формате.
Интересно ы Вас получается. Вообщем то мне известно что в теории микропроцессоров (а точнее архитектуры "общая шина") внешние устройства представляются как участок памяти (ОЗУ). Но это лишь для драйверов этих устройств и как буфер обмена данными. Когда же мы говорим о коде программы, выполняемой не как драйвер устройства, мы должны разделять физическое ОЗУ и физичекие файлы на внешних устройствах. Другими словами команды ЦПУ, иные чем команды ввода-вывода не могут напрямую адркссовать блоки данных на дисках. Это имеено то что имеет отношения к обсуждаемой здесь "виртуальной памяти". Собственно и Вы об этом сказали, говоря: "Поэтому без кеша в оперативной памяти обойтись не получится."
Хотя теоретически, можно было бы сделать аппаратную поддержку, вовлечь контролер диска в процедуру отображения, и резервировать на диске место в специальном формате. ....
Почему теоритически? Это есть в каждой современной системе. Это и есть часть работы с виртуальной памятью. В каждой системе есть "место на диске" (Page file) куда система сбрасывает/вытесняет содержимое страниц ОЗУ с целью их освобождения для содержимого страниц ранее вытесненых в этот файл, но востребованных процессом. А как иначе? Ведь сумма размеров материализованных адресных пространств всех процессов как правило превышает размер ОЗУ (физической памяти). .
Другими словами команды ЦПУ, иные чем команды ввода-вывода не могут напрямую адресовать блоки данных на дисках. Это именно то что имеет отношения к обсуждаемой здесь "виртуальной памяти".
Виртуальным адресам памяти. Память всегда реальна, и существует в физическом виде.
Я понимаю о чем вы говорите. Но все пишут по разному. Одни пишут "виртуальная память", другие "виртуальное адресное пространство".
Почему теоретически? Это есть в каждой современной системе. Это и есть часть работы с виртуальной памятью.
Это программные процедуры. Теоретически их можно сделать аппаратными.
Это программные процедуры. Теоретически их можно сделать аппаратными.
На самом деле "виртуальная память" это программно-аппартная процедура. Преобразование виртуального адреса в физический (или реальный), в том случае когда страница виртуальной памяти находится в ОЗУ (это называется frame), выполняется аппаратными средствами (DAT) c использованием таблицы страниц, а когда страница не в ОЗУ, то включается программная процедура, по прерыванию отсутствия страницы от DAT, и программно эта страница загружается с диска (из Page file) в ОЗУ, затем модифицируется таблица страниц и выполнение команды повторяется.
ОС постоянно пробегает линейно список vm_area_struct?
В какой момент и при каких обстоятельствах система отказывает в выделении виртуальной памяти процессу?
Виртуальную память можно выделять до тех пор, пока все виртуальное адресное пространство не будет занято регионами памяти. Однако это не совсем правда, потому что системным вызовам brk и mmap подлежат только некоторые регионы виртуального адресного пространства, а именно куча (для brk) и регион отображений, называемый memory-mapped region. Не все виртуальные страницы связаны с физическими. Ответ как связаны отвечу в следующих сериях, но если очень кратко сейчас - при первом обращении, что зарубежные источники называют demand paging.
По поводу линейного прохода списка vm_area_struct. Честно не знаю в каких случаях линейно, а в каких нет, но можно обратить внимание на два поля структуры mm_struct: mmap и mm_rb. В лучших традициях Linux красно-черное дерево используется для поиска, а линейный список для обработок.
Вот с чего примерно надо было бы начинать рассказа про виртуальную память:
A Translation Lookaside Buffer (TLB) is a high-speed cache within a processor's Memory Management Unit (MMU) that stores recent translations of virtual memory addresses to physical memory addresses, acting as an address-translation cache to speed up memory access by avoiding slow page table lookups in main memory. When the CPU needs a memory location, it first checks the TLB (a TLB Hit); if found, the physical address is quickly provided, but if not (a TLB Miss), the system must consult the page tables, which is slower, requiring hardware or OS intervention. TLBs are crucial for performance, as they reduce multiple memory accesses to potentially just one, using locality of reference to cache frequently used mappings.
How it Works
Virtual to Physical: The TLB maps a Virtual Page Number (VPN) to a Physical Page Frame.
Lookup: A virtual address is broken down; the MMU uses the VPN to check the TLB.
Hit: If the translation is in the TLB, the physical address is returned instantly, saving significant time.
Miss: If not, the page table in main memory is accessed (often involving multiple memory reads), and the new translation is added to the TLB, potentially evicting an old entry.
Да, если мы бы рассматривали таблицы страниц и как виртуальная память действительно связана с физической. Данная работа (по крайней эта часть работы) посвящана исключительно рассмотрению структур ядра, системных вызовов и структур, которые в последствии будут связаны со стандартной библиотекой Glibc, вызовом malloc и особенностью загрузки страниц в физическую память.
Возможно, под "особенностью работы с физической памятью" Вы желали увидеть связку MMU, TLB, Page tables, загрузка по надобности (demand paging), двоичный аллокатор "друзей" и, что уже написано, mm_struct и vm_area_struct. В следующих публикациях постараюсь ввести это понятие конкретнее.
Данная работа (по крайней эта часть работы) посвящана исключительно рассмотрению структур ядра, системных вызовов и структур, которые в последствии будут связаны со стандартной библиотекой Glibc, вызовом malloc
Вот с этого и надо было начинать, с malloc, и лишь потом вводить виртуальную память. Но Вы начаи именно с виртуальной памяти. И не до конца разобравшись с ней приступили к управлению памятью ядром Линукс. Получилось пока не то ни сё, ни рыба ни мясо.
Жду следуших частей. Я брал курсы ИБМ по Линукс, но это было давно, так давно что уже практически ничего не помню, а конспекты лекций при очередном переезде непредусматрительно выбросил. Но тогда помню мне было всё просто и понятно. А сейчас ничего не понимаю из Вашей статьи.
Регион памяти
0x0000 7FFF FFFF F000-0xFFFF FFFF FFFF FFFFиспользуется операционной системой и имеет адресуемый размер в 128ТБ
после такого ляпа дальше читать не стал ...
есть же калькулятор
Особенности работы с физической памятью в ОС Linux, часть 1