Когда растет стек? Как ОС знает, когда вырастить стек? - PullRequest
6 голосов
/ 03 марта 2020

Примечание. Этот вопрос касается архитектуры x86_64 и Linux ABI.

Когда программа запускается, для стека выделяется некоторое пространство. Позже, во время выполнения программы, область стека может быть изменена (когда требуется больше места) до некоторого максимума, определенного ОС.

Давайте возьмем, например, простую программу:

int main() {
    char bytes[7 * 1024 * 1024];
}

Давайте запустите его под GDB и установите точки останова: перед main и после объявления массива.

gdb> b *main
gdb> b main
gdb> r
gdb> info proc mapping // breakpoint before pushing stack
          Start Addr           End Addr       Size     Offset objfile
      0x7ffffffde000     0x7ffffffff000    0x21000        0x0 [stack]
gdb> c
gdb> info proc mapping // breakpoint after pushing stack
          Start Addr           End Addr       Size     Offset objfile
      0x7fffff8fe000     0x7ffffffff000   0x701000        0x0 [stack]

Таким образом, мы можем видеть, что размер стека действительно изменился.

Вопрос в том, как ОС знает, когда нужно изменить размер стека? . Некоторые ресурсы inte rnet говорят, что ОС обрабатывает page fault exception, и если доступный адрес находится в пределах возможного диапазона адресов стека, он изменяется.

Но когда я шаг за шагом отлаживал программу, оказалось, что размер стека изменился сразу после следующей инструкции:

0x40129d <main+4>     sub    rsp, 0x700010

Итак, насколько я знаю, есть нет page fault пока, поскольку мы на самом деле не обращаемся к адресам. Мы только меняем rsp регистр. Так как это возможно, ОС справляется с этим? Или может быть page fault exception после изменения rsp?

1 Ответ

2 голосов
/ 03 марта 2020

Но когда я шаг за шагом отлаживал программу, оказалось, что размер стека изменился сразу после следующей инструкции:

0x40129d <main+4>     sub    rsp, 0x700010

Это не правильно. Если вы выполняете пошаговое выполнение показанной вами программы (даже если она скомпилирована без оптимизаций), сопоставление вообще не увеличивается, поскольку нет записей в страницы стека.

Но даже если вы выполняете менее простую программу вы также увидите, что отображение не меняется в инструкции sub, а скорее при каждом постоянно увеличивающемся доступе к стеку.

Например, если вы выполните:

bytes[0] = 42;

вы увидите, что он увеличивается на 0x70000, поскольку вы пишете в верхнюю часть. Но если вы вместо этого сделаете что-то вроде:

bytes[3 * 1024 * 1024] = 42;

Вы увидите, что оно увеличивается только на 0x40000.

Обратите внимание, что вы можете запутаться, если выполняете инструкцию, которая происходит с пу sh в стек, как call.

...