Как можно использовать двусвязный список в Buddy аллокаторе для управления свободными блоками памяти?

Как организовать работу с двусвязным списком таким образом, чтобы избежать проблем при удалении дочерних блоков из списка при выделении их отца?
  • 8 февраля 2024 г. 18:49
Ответы на вопрос 2
Buddy аллокатор — это метод управления памятью, который разбивает память на блоки различного размера, чтобы удовлетворить запросы на выделение памяти. Эта система позволяет эффективно объединять (coalesce) и разбивать (split) блоки памяти, чтобы минимизировать фрагментацию.

Двусвязный список в Buddy аллокаторе может быть использован для управления свободными блоками памяти следующим образом:

1. Списки свободных блоков: Использовать отдельный двусвязный список для свободных блоков каждого возможного размера. Например, если минимальный размер блока равен 2^k байт, вы создаёте двусвязный список для блоков размером 2^k, 2^(k+1), 2^(k+2), и так далее.

2. Выделение памяти: Когда происходит запрос на выделение памяти размером N, аллокатор ищет в соответствующем списке двусвязных блоков, которые могут содержать блок подходящего размера. Если свободного блока нужного размера нет, он может выделить больший блок и разбить его на два "buddy" блока. Один из этих блоков используется для удовлетворения запроса на выделение, а другой возвращается в список свободных блоков.

3. Освобождение памяти: Когда блок памяти освобождается, он возвращается обратно в свой двусвязный список. Аллокатор проверяет, существует ли соседний свободный блок того же размера (его "buddy"), и если да, то он объединяет эти два блока в один больший, удаляя их из двусвязного списка и вставляя объединенный блок обратно в соответствующий список для большего размера.

4. Поддержка двусвязного списка: Каждый элемент двусвязного списка содержит указатели на предыдущий и следующий элементы. Это позволяет эффективно добавлять и удалять блоки в списке, так как вам не нужно перемещаться по всему списку для выполнения этих операций.

Чтобы избежать проблемы удаления дочерних блоков из списка при выделении их отца, можно воспользоваться отметкой (tagging) блоков. Эти отметки могут следить за статусом блоков (например, свободный или занятый), и когда блок выделяется, его дочерние блоки могут быть автоматически идентифицированы как занятые даже без необходимости удалять их из списка. На этот момент, когда блок выделяется, система может взять только блок верхнего уровня, не заботясь о дочерних блоках, потому что их состояние теперь известно и помечено как занятое.

Также может быть реализован механизм, который предотвратит освобождение дочерних блоков, пока родительский блок занят. Это может включать ссылки на родительские блоки или какой-то механизм счетчиков ссылок, который отслеживает использование дочерних блоков.
И пофигу на порядок. Пусть он в списках будет произвольный. При выделении блока просто берете первый из списка, удаляете оттуда и выдаете. При освобождении блока пихаете его в список куда угодно. 

Только надо поддерживать еще указатели на buddy. Т.е. тут что-то вроде трех-связного списка будет. При освобождении бока, если видите, что его buddy свободен, то удаляете его их обоих из списка и "освобождаете" удвоенный кусок.

Можно это в массиве делать и хранить указатели вперед-назад в двух элементах под двух buddy. У вас в списке же только один из парочки всегда может быть.
Похожие вопросы