Распределитель памяти — простое раздельное хранилище: как определить размер выделенного блока по его адресу?

Я читаю книгу по CS:APP и наткнулся на Simple Segregated Storage в главе Dynamic Memory Allocation.
В книге упоминается, что одним из преимуществ Simple Segregated Storage является то, что блоки памяти не нуждаются в заголовке. Он упоминает

Поскольку каждый фрагмент состоит только из блоков одинакового размера, размер выделенного блока можно определить по его адресу.

Изображение из книги - CS:APP - Простое отдельное хранилище
Я не понимаю, как это работает. Я понимаю, что, поскольку размер блоков одинаков для одного свободного списка, адрес каждого блока будет сначала увеличиваться на ту же сумму, когда большой блок запрашивается из ядра и делится, но как мы можем вывести размер из адреса ? Он должен быть кратен размеру блока, но если начальный начальный адрес не кратен, то он никогда не будет кратен размеру блока. Более того, если классы размера идут, 2, 4, 8, 16, адрес может быть кратен многим другим классам размера?

В нем говорится ... блоки одинакового размера в каждом фрагменте ... Если у вас есть все блоки размера M в одном выделенном фрагменте памяти, вы можете узнать из адреса блока, в каком фрагменте памяти он находится, и поэтому он его размер М.

Weather Vane 08.04.2023 19:18

Программное обеспечение для выделения памяти просто устанавливает области памяти. Например, от 0x1000000 до 0x2000000 используются для восьмибайтовых блоков, от 0x2000000 до 0x3000000 — для 16-байтовых блоков, от 0x3000000 до 0x4000000 — для 32-байтовых блоков и т. д. Или, возможно, более реалистично, каждый раз, когда программному обеспечению требуется новый регион памяти, либо потому, что был запрошен новый размер, либо из-за того, что старый регион заполнен, он выделяет кучу памяти, запоминает, где он начинается и для какого размера он предназначен, и использует его только для блоков такого размера. Затем free ищет возвращенные блоки в запомненных начальных адресах.

Eric Postpischil 08.04.2023 19:20

Далее идет речь о связанном списке свободных (доступных) блоков. Когда требуется блок памяти, он берется из головы связанного списка (для этого размера блока), а когда он освобождается, он становится головным блоком связанного списка.

Weather Vane 08.04.2023 19:23

@EricPostpischil единственное, что Simple Segregated Storage не встраивает эту информацию в блоки памяти. В книге упоминается, что ей не нужен верхний или нижний колонтитул. В нем говорится, что это возможно, потому что «размер выделенного блока можно определить по его адресу», что меня сбивает с толку. Как узнать размер по адресу?

BSE10 08.04.2023 21:36
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
75
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Распределитель, использующий этот подход, получает большие блоки (фрагменты) памяти от ОС. Он определяет размер блока, используемый для выделения блоков из каждого фрагмента, и ключом к «простому раздельному хранилищу» является то, что каждое выделение из данного фрагмента будет точно такого же размера. Это может быть больше, чем запрошенный размер для любого данного запроса, но это не редкость для распределителей в целом. Таким образом, чтобы определить (истинный) размер данного распределения, распределителю нужно только определить, в каком фрагменте он находится. Ему не нужна какая-либо информация о распределении.

Я понимаю, что распределителю нужно только знать, к какому фрагменту (свободному списку) должен вернуться выделенный блок при освобождении, но как он узнает об этом из адреса выделенного блока? Я знаю, что блоки в одном и том же чанке имеют одинаковый размер, но я не уверен, как это помогает, когда чанк (свободный список) может начинаться со случайного места в памяти.

BSE10 08.04.2023 21:32

@ BSE10, где-то у него есть записи базового адреса и размера каждого фрагмента на уровне фрагментов. Или, что то же самое, начальный и конечный адреса каждого фрагмента. Ему не нужны заголовки для каждого распределения, но ему все же нужны некоторые метаданные.

John Bollinger 09.04.2023 19:34

Если это так, то блоки могут быть любого размера в пределах диапазона размера класса, и вы все равно можете узнать, к какому фрагменту принадлежит блок, если вы просто сравниваете адрес блока с начальным и конечным адресами фрагмента. В книге конкретно упоминается причина в том, что блоки в одном фрагменте имеют одинаковые размеры, и поэтому размер можно определить по адресу блока. Это та часть, которую я пытаюсь понять

BSE10 10.04.2023 00:10

@ BSE10, да, все дело в том, что адрес выделенного блока говорит вам, к какому фрагменту он принадлежит. И поскольку все блоки, выделенные из данного фрагмента, имеют одинаковый (истинный) размер, это говорит вам о размере выделения. И именно поэтому с этой схемой вам не нужно вести записи размера выделения для каждого выделения.

John Bollinger 10.04.2023 15:40

Ах хорошо. Теперь это имеет гораздо больше смысла! Большое спасибо! :)

BSE10 10.04.2023 19:31

Я полностью понимаю, что вы имеете в виду, потому что я пытаюсь использовать этот метод в malloclab и найти эту проблему.

Я согласен, что мы не можем вычислить размер блока по адресу, если адрес &(4KB-1) равен 32, это может быть 5-й для 8, 3-й для 16 или 1-й для 32. А если адрес равен 0, он может быть первым блоком для любого размера.

Поэтому мы должны использовать дополнительное пространство для записи некоторой информации.

Одним из решений является запись начального адреса каждого фрагмента и того, к какому свободному списку он принадлежит, а затем, если мы получим свободный адрес void* ptr, выполните поиск (ptr & ~ 4 КБ) в списке фрагментов, чтобы найти соответствующий размер блока. Но это так глупо и трудно кодировать.

Другим решением является добавление заголовка. И я выбираю закончить таким образом.

Другие вопросы по теме