Думаю, на ваш вопрос можно легко написать хоть несколько глав для книги по Операционным системам. Предлагаю вам прочитать Таненбаум: Современные операционные системы.
Основное различие кучи и стека в том, что один для каждого элемента процесса, другой для элемента потока. Первоначально, когда программа запускается, она получает некоторую минимальную кучу и некоторый сегмент стека. Куча увеличена, стек статичен (для каждого потока). Если вы напишете рекурсивную функцию, которая не завершается (бесконечная рекурсия), вы получите переполнение стека;) Любой вызов функции имеет фрейм стека в сегменте стека, когда функция уходит, стек разматывается, и фрейм может использоваться следующая функция. Стек представляет собой непрерывную линейную структуру. В Linux вы можете настроить размер сегмента стека для процесса с помощью переменной среды. В Windows (по крайней мере, с MS Visual C ++) вы можете передать флаг компоновщика с размером сегмента стека. Переполнение стека также может происходить при выделении во время компиляции некоторого большого массива:
char test[1000000];
Куча - это отдельная история. Когда процесс запускается, размер кучи является некоторым значением по умолчанию и может варьироваться от ОС к ОС или конфигурации, используемой в этой ОС (например, в Windows это 2 МБ по умолчанию, насколько я помню). Кроме того, если вам нужно больше кучи, чтобы выделить больше места для переменных и т. Д., Она будет расти. Если программа не освобождает память кучи, она исчерпывается (или пространство кучи). Существуют разные структуры данных для реализации кучи, некоторые из них являются производными двоичного дерева, некоторые нет, например. Куча Фибоначчи (лес из деревьев). Вы можете прочитать статьи и т. Д. О том, как написать распределитель памяти. Эти структуры данных должны быть оптимизированы для поиска узла кучи, когда выделенный фрагмент необходимо отменить, или добавления (нахождения свободного фрагмента), когда требуется новое пространство кучи.
Каждый процесс в 32-битной ОС имеет 4 ГБ виртуального адресного пространства. Как вы понимаете, оперативной памяти не может быть столько, чтобы поместились все процессы с их 4 ГБ виртуального адресного пространства. Память ОС организована в виде страниц, которые заменяются на HD, когда они больше не нужны или срок их действия истек. Здесь на помощь приходит пейджинг. На страницы отображается все: процесс со стеком или растущая куча. Благодаря динамической структуре кучи, ее можно разместить на нескольких страницах. Вот почему доступ к куче может быть очень дорогостоящим, потому что, если страница не находится в памяти, происходит сбой страницы, и ОС должна загружать страницу с диска (а это может быть намного медленнее). Кадр стека выполняемого потока находится в кеш-памяти процессора, который намного быстрее ОЗУ.
Возможны разные типы кучи, могут быть кучи, которые очень быстро работают для небольших объектов, или кучи, которые очень эффективны в многопоточных средах. Александреску описывает в «Современном дизайне C ++», как разработать распределитель небольших объектов и кучу, которая управляет небольшими объектами. Эта реализация доступна в его библиотеке Loki C ++. Некоторые встроенные системы предлагают физически разные области памяти, где могут быть реализованы различные типы кучи. Написать собственный распределитель (диспетчер кучи и т. Д.) - тяжелая работа, если вы хотите превзойти компилятор.
С уважением,
Ованес
person
ovanes
schedule
31.07.2009