На уроке «Операционные системы» мы упоминали виртуальную память как механизм, который абстрагирует физическую память для процесса, и что она выглядит примерно так (для каждого процесса):
Стек увеличивает адреса памяти, а куча увеличивает адреса памяти. Начальный адрес стека — это практически максимальный адрес адресного пространства (около 2^64 — 1 на 64-битном процессоре).
Я понимаю виртуальную память, стек и кучу, но не понимаю, почему размер стека должен быть ограничен всего парой МБ, исходя из этой картины (на практике стеки составляют всего несколько МБ из-за кэширования и больших размеров стека). указать на проблему в коде). Теоретически переполнение стека должно происходить только тогда, когда у нас заканчивается системная память, а не когда мы заполняем 1-3 МБ.
Мой вопрос: есть ли еще одна линия разрыва, которую мне не хватает на этом изображении, которая устанавливается компилятором/компоновщиком/операционной системой и отмечает максимальный размер стека?
@user3344003 user3344003 Я не совсем понял, что ты имеешь в виду
Одним из примеров является «блок управления процессом» — вымышленная конструкция, изобретенная в учебниках по плохим операционным системам. Структуры, выполняющие такие функции, не расположены в пользовательском пространстве. Во-вторых, это слишком упрощено, поскольку все так изложено только в простом примере. Другая причина заключается в том, что все адресное пространство редко доступно приложению.
Если не считать абсолютно сумасшедших уровней рекурсии, нет реальной необходимости иметь стек размером хотя бы около гигабайта.
Поскольку вы обычно заранее знаете, какого уровня стека будет достаточно, вполне приемлемо ограничить размер стека и разрешить беспрепятственный доступ к куче. Стек размером 1 М на самом деле довольно велик, если вы помещаете только базовые типы (включая указатели). Например, если усреднить (и это немало) десять восьмибайтовых параметров на вызов (и удвоить их для дополнительного использования административного стека), то это более 6000 уровней стека, которые вы можете пройти, не исчерпав стек.
И имейте в виду, что если вашему стеку позволить беспрепятственно расти (и это, вероятно, является ошибкой программирования, как вы утверждаете), это, вероятно, повлияет на другие процессы с точки зрения обмена.
Чтобы ответить на ваш конкретный вопрос (о дополнительной «линии разрыва»): иногда размер стека устанавливается компоновщиком, когда он объединяет все объектные файлы в исполняемый файл. Например, я считаю, что редактор связей GNU ld
использует (или когда-то использовал) сценарий с указанным размером стека.
Я смутно помню, как пользовался системами (давно)(1), где размер стека был жестко запрограммирован в компоновщике и был достаточно мал, чтобы причинить нам горе. Следовательно, мы просто использовали основной поток для запуска другого потока (без ограничения размера, поскольку стек был где-то выделен из кучи) для выполнения реальной работы. Затем основной поток просто ждал завершения другого потока.
Вы абсолютно правы в том, что вы могли бы просто разделить это пространство между низом кучи и верхом стека, чтобы они оба могли свободно его использовать.
(1) Ограничение распространялось только на исходный стек, настроенный загрузчиком программы на основе информации из исполняемого файла. Даже сейчас это ограничение может применяться, а может и не применяться к стекам, создаваемым на лету при создании дополнительных потоков внутри процесса.
То есть конечная строка стека не существует в концепции виртуальной памяти, но она существует, когда компоновщик завершает свою работу?
@lukascobbler: могут существовать искусственные ограничения, такие как фиксированный селектор Intel с ограниченным размером 2 МБ, который не расширяется, когда вы его исчерпаете (или даже тот, который может быть расширен операционной системой, но он решает прекратить расширение на 8 МБ), но эти на самом деле это детали реализации. В обычном 64-битном адресном пространстве с плоской моделью существование этих ограничений не требуется.
Это имеет большой смысл и отвечает на мой вопрос. Спасибо.
Эта картина страдает от серьезной депривации реальности.