Каким образом операционная система определяет начальные адреса сегментов всех программ при загрузке процесса и выделении памяти? Почему начальные адреса всех сегментов имеют один адрес и как это влияет на эффективность TLB (буфера трансляции адресов)? Возможно ли, что ОС рандомизирует порядок выделения виртуальных адресов для повышения эффективности?
Виртуальные адреса для поиска формируются путем преобразования линейных адресов, которые генерируются программой, в физические адреса доступные в памяти. Обычно виртуальные адреса содержат номер сегмента (например, код, данные, стек) и смещение внутри данного сегмента. Программы, начинающиеся с одних адресов, могут иметь общий базовый адрес или общую область памяти, куда они загружаются при старте. Операционная система определяет начальные адреса сегментов всех программ при загрузке процесса и выделении памяти через механизмы управления виртуальной памятью. Начальные адреса всех сегментов могут быть одинаковыми для упрощения работы с адресами и увеличения эффективности кэша TLB. TLB хранит соответствие виртуальных и физических адресов, и если начальные адреса сегментов различаются, это приведет к увеличению количества несовпадений в TLB и ухудшению его эффективности. Операционная система может использовать методы рандомизации адресного пространства, такие как ASLR (Address Space Layout Randomization), чтобы повысить безопасность системы и снизить риск успешных атак на внедрение зловредного кода. Однако рандомизация адресного пространства может привести к усложнению работы с памятью и увеличению накладных расходов на управление адресами, поэтому ее использование должно быть взвешено с другими аспектами производительности системы.
Ты уже сказал про старшие 20 бит, скорее всего знаешь про сегментную организацию виртуальной памяти.
20 бит используются в 32 битных системах, а сейчас большая часть 64 битная, но это не важно.
Принцип следующий:
Существует 3 таблицы:
- PGD - Page Global Directory
- PMD - Page Middle Directory
- PTE - Page Table Entry
Они иерархические, т.е. запись в PGD указывает на запись в PMD, а PMD - на PTE.
В итоге, ты приходишь с 3 "числами" - индексы для этих таблиц и последовательно приходишь к нужной PTE.
Но тебе нужно еще 4 число - смещение относительно полученного в PTE значения (там хранятся "начала" выделенных сегментов/интервалов памяти)
Теперь последовательно запиши эти адреса и получишь виртуальный адрес.
TLB в данном случае - это просто кэш, чтобы ты постоянно не ходил через этот ад указателей. Он в процессе выделения памяти не участвует.
Как выделяется реальная память - деталь реализации, о которой знать не нужно.
Если интересно - вот статья про память в линуксе.
P.S. пример показан на C# - там собственная виртуальная память и GC. Поэтому показывает не то, что выделила ОС.