Кроме malloc / free, нужна ли программе операционная система для предоставления чего-либо еще?
-
10-07-2019 - |
Вопрос
Я работаю над разработкой ядра (которое я собираюсь на самом деле называть "ядром", просто чтобы отличаться, но в основном оно то же самое) для операционной системы, над которой я работаю.Специфика самой операционной системы не имеет значения, если я не могу запустить многозадачность, управление памятью и другие базовые вещи, поэтому мне нужно сначала поработать над этим.У меня есть несколько вопросов о разработке процедуры malloc.
Я полагаю, что malloc() будет либо частью самого ядра (я склоняюсь к этому), либо частью программы, но в любом случае мне придется написать свою собственную реализацию стандартной библиотеки C, поэтому я могу написать malloc .Мой вопрос на самом деле довольно прост в этом отношении: как C (или C ++) управляет своей кучей?
Чему меня всегда учили на теоретических занятиях, так это тому, что куча - это постоянно расширяющийся фрагмент памяти, начинающийся с указанного адреса и во многих смыслах ведущий себя как стек.Таким образом, я знаю, что переменные, объявленные в глобальной области видимости, находятся в начале, и другие переменные "помещаются" в кучу по мере их объявления в соответствующих областях видимости, а переменные, которые выходят за пределы области видимости, просто остаются в пространстве памяти, но это пространство помечено как свободное, поэтому куча может расширяться больше, если это необходимо.
Что мне нужно знать, так это то, каким образом C на самом деле обрабатывает динамически расширяющуюся кучу таким образом?Выполняет ли скомпилированная программа на C свои собственные вызовы подпрограммы malloc и обрабатывает свою собственную кучу, или мне нужно предоставить ей автоматически расширяющееся пространство?Кроме того, как программа на C узнает, где начинается куча?
О, и я знаю, что те же концепции применимы к другим языкам, но я бы хотел, чтобы любые примеры были на C / C ++, потому что мне больше всего нравится этот язык.Я также хотел бы не беспокоиться о других вещах, таких как стек, поскольку я думаю, что смогу справиться с подобными вещами самостоятельно.
Итак, я полагаю, мой реальный вопрос заключается в том, кроме malloc / free (который обрабатывает получение и освобождение страниц для себя и т.д.), нужна ли программе операционная система для предоставления чего-либо еще?
Спасибо!
Редактировать Меня больше интересует, как C использует malloc по отношению к куче, чем фактическая работа самой подпрограммы malloc.Если это поможет, я делаю это на x86, но C является кросс-компилятором, так что это не должно иметь значения.^_^
РЕДАКТИРОВАТЬ ДАЛЬШЕ:Я понимаю, что, возможно, путаю термины.Меня учили, что "куча" - это место, где программа хранит такие вещи, как глобальные / локальные переменные.Я привык иметь дело со "стеком" в программировании на ассемблере, и я только что понял, что, вероятно, имею в виду именно это.Небольшое исследование с моей стороны показывает, что "куча" чаще используется для обозначения общего объема памяти, который программа выделила для себя, или общего количества (и порядка) страниц памяти, предоставленных операционной системой.
Итак, имея это в виду, как мне справиться с постоянно расширяющимся стек?(действительно, похоже, что мой урок теории Си прошел мягко...ущербный.)
Решение
malloc
обычно реализуется в среде выполнения C в пользовательском пространстве, полагаясь на определенные системные вызовы ОС для отображения страниц виртуальной памяти.Работа malloc
и free
заключается в управлении теми страницами памяти, размер которых фиксирован (обычно 4 КБ, но иногда и больше), а также в разделении их на части, которые могут использовать приложения.
См., например, GNU libc выполнение.
Для более простой реализации ознакомьтесь с Операционные системы MIT класс прошлого года.В частности, см. заключительный лабораторный раздаточный материал, и взгляните на lib/malloc.c
.Этот код использует операционную систему JOS, разработанную в классе.Принцип работы заключается в том, что он считывает таблицы страниц (предоставляемые ОС только для чтения) в поисках несопоставленных диапазонов виртуальных адресов.Затем он использует sys_page_alloc
и sys_page_unmap
системные вызовы для сопоставления и отмены сопоставления страниц с текущим процессом.
Другие советы
Есть несколько способов решить проблему.
Чаще всего программы на языке C имеют собственную функциональность malloc/free.Этот подойдет для небольших объектов.Изначально (и как только память закончится) менеджер памяти запросит у ОС больше памяти.Традиционными методами для этого являются mmap и sbrk в вариантах unix (GlobalAlloc/LocalAlloc в Win32).
Предлагаю вам взглянуть на Распределитель памяти Дуга Ли (Google:dlmalloc) от поставщика памяти (например.ОС) точка зрения.Этот распределитель очень хорош и имеет возможности для всех основных операционных систем.Если вы хотите знать, чего высокопроизводительный распределитель ожидает от ОС, этот код — ваш первый выбор.
Вы путаете кучу и стек?
Я спрашиваю, потому что вы упоминаете «постоянно расширяющуюся часть памяти», область видимости и помещение переменных в кучу по мере их объявления.Звучит так, будто вы на самом деле говорите о стеке.
В наиболее распространенных реализациях C объявления автоматических переменных, таких как
интервал я;
обычно приведут к тому, что i будет выделено в стеке.В общем случае, malloc не будет задействован, если вы явно не вызовете его или его не вызовет какой-либо библиотечный вызов.
Я бы порекомендовал посмотреть «Экспертное программирование на C» Питера Ван Дер Линдена, чтобы узнать, как программы на C обычно работают со стеком и кучей.
Обязательное чтение:Кнут - Искусство компьютерного программирования, Том 1, Глава 2, Раздел 2.5.В противном случае вы можете прочитать Кернигана и Ритчи «Язык программирования C», чтобы увидеть реализацию;или вы можете прочитать Плаугера «Стандартная библиотека C», чтобы увидеть другую реализацию.
Я считаю, что то, что вам нужно делать внутри вашего ядра, будет несколько отличаться от того, что видят программы вне ядра.В частности, распределение памяти внутри ядра для программ будет связано с виртуальной памятью и т. д., тогда как программы вне кода просто видят результаты того, что предоставило ядро.
Прочтите об управлении виртуальной памятью (подкачка).Он сильно зависит от ЦП, и каждая ОС реализует управление виртуальными машинами специально для каждого поддерживаемого ЦП.Если вы пишете свою ОС для x86/amd64, прочтите соответствующие руководства.
Обычно библиотека C занимается реализацией malloc
, запрашивая память у ОС (либо через анонимный mmap
или, в старых системах, sbrk
) как надо.Таким образом, ваша часть ядра должна обрабатывать выделение целых страниц с помощью чего-то вроде одного из этих способов.
Тогда дело за malloc
распределять память таким образом, чтобы не слишком сильно фрагментировать свободную память.я не слишком свершилось однако с подробностями этого;однако термин арена приходит в голову.Если мне удастся найти ссылку, я обновлю этот пост.
Опасность, опасность!!Если вы даже рассматриваете возможность попытки разработки ядра, вы должны быть очень хорошо осведомлены о стоимость о ваших ресурсах и их относительно ограниченной доступности...
Одна вещь о рекурсии заключается в том, что она очень дорогая (по крайней мере, в области ядра), вы не увидите многих функций, написанных для простого продолжения без ограничений, иначе ваше ядро запаникует.
Чтобы подчеркнуть мою точку зрения здесь, (на stackoverflow.com хех), ознакомьтесь с этим сообщением из Блог по отладке NT о переполнении стека ядра, в частности,
· На платформах, основанных на x86, стек режима ядра равен 12K.
· На платформах на базе x64 стек режима ядра равен 24K.(платформы на базе x64 включают системы с процессорами, использующими архитектуру AMD64 , и процессорами, использующими архитектуру Intel EM64T).
· На платформах на базе Itanium стек режима ядра равен 32K с помощью 32K резервный магазин.
На самом деле это не так уж много;
Обычные Подозреваемые
1.Щедро используя стек.
2.Рекурсивный вызов функций.
Если вы немного почитаете блог, то увидите, насколько сложной может быть разработка ядра с довольно уникальным набором проблем.Ваш урок теории не был неправильным, это было просто-напросто.;)
Если исходить из теории -> разработка ядра примерно так же важна, как контекст переключайтесь, насколько это возможно (возможно, сохраните некоторое взаимодействие с гипервизором в миксе !!).
Во всяком случае, никогда не предполагайте, не подтверждайте и не проверяйте свои ожидания.