2015-12-31 3 views
2

Недавно я попытался представить себе, как стек памяти, вероятно, рассматривается внутри ядра Linux, но не может придумать что-либо твердое. Я знаю, что ядро ​​использует свои собственные функции для управления динамической памятью, но я понятия не имею, как он управляет только нормальной памятью стека C, потому что в конце концов это может быть реализовано с помощью обычного C и скомпилировано с помощью обычного GCC. Насколько мне известно, распределение памяти в стеке обычно рассматривается с помощью формы libc при работе с операционными системами и даже над чем-то вроде AVR. Насколько мне известно, хотя ядро ​​Linux не зависит от libc?Ячейка стека внутри ядра Linux

Я не совсем уверен, как управление памятью стека делегировано в libc в первую очередь, хотя, как представляется, это встроенная функция языка. Все, что я могу себе представить, это то, что он каким-то образом обобщен (или реализован) таким образом, что провайдер может быть назначен либо позже, либо, возможно, как часть процесса компиляции. Может ли кто-нибудь пролить свет на это для меня?

+0

Когда начинается новый процесс, он имеет стек пользовательского пространства, отображаемый в адресное пространство процесса, и стек ядра для использования при выполнении системных вызовов. Указатель стека начинает указывать на стек. libc не участвует в этом * вообще *. Опубликованный ответ несколько сбивает с толку, но, похоже, правильно, что двоичные файлы ELF могут контролировать, какую конфигурацию стека они получают: http://stackoverflow.com/questions/18278803/how-does-elf-file-format -defines-зе-стек. По умолчанию не будет такого раздела, а затем вы получите стек по умолчанию при выборе по умолчанию аргумента virt. –

ответ

0

Насколько он у меня, стек распределения памяти, как правило, рассматривается по формой LIBC ...

Эта программа показывает, что ничего из LIBC не используется для выделения стека памяти:

// compile with: gcc -nostdlib nolibc.c -o nolibc 
_start() 
{ 
    int a[9999]; 
    *a = 0; 
    asm(" mov %0,%%ebx\n\ 
      mov $1,%%eax\n\ 
      int $128" : : "r" (*a)); // _exit(*a); 
} 

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

0

Общая память стека выделяется (весь стек) во время этапа ссылки.

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

Код .startup (как правило, функция сборки в некоторой библиотеке, я не уверен, какая библиотека) находит имя секции .stack в загруженном коде, добавляет значение длины, чтобы получить верхний адрес стека (стеки растут вниз) и (среди нескольких других операций) устанавливает регистры sp и bp.

Когда ОС работает (I.E. не в режиме «пользователь»), он (как правило) имеет свое собственное пространство стека и использует свои собственные значения для регистрови bp.

Переключение между режимом «пользователь» и «привилегированным» режимом и обмен значениями регистров обрабатывается в переходах между тем, что вы написали, и кодом в ядре.

Большая часть такого рода переключений обрабатывается в функциях обертки в библиотеке libc, и результирующее управление переходит через таблицу переходов в подпрограммы ядра.

Примечание: другие процессоры и ОС имеют разные детали о том, как дела обстоят, но результаты очень похожи.

+0

Я не могу найти сегмент .stack в современном Linux. '% objdump -h/bin/cat' –

+0

возможно, вы могли бы прочитать этот вопрос stackoverflow, чтобы найти ответы, которые вы ищете: user3629249

+1

Сохранение/восстановление регистров и свопинг в стек ядра, * не * обрабатывается libc. Ядро не может доверять libc, потому что libc - это просто код пользовательского пространства, запускаемый непривилегированными процессами! Кроме того, это должно произойти и работать одинаково, когда вы делаете системный вызов «напрямую» (например, с инструкцией 'syscall' в 64-битном режиме), даже для игрушечных исполняемых файлов, которые не связывают библиотеки. –

0

Стек может быть любым блоком памяти чтения/записи. В стеке нет ничего особенного. Операционная система создает стек, то есть он выделяет память и назначает ее местоположению регистру указателя стека, потому что для запуска процесса требуется один, но он не управляет стеком.

В unix-land запуск программы осуществляется в два этапа. Во-первых, вы клонируете родительский процесс. Таким образом, новый процесс имеет те же настройки стека, что и родительский.

Наконец, вы выполняете программу. Загрузка программы получает требуемый размер стека из исполняемого файла, который, в свою очередь, получает информацию от компоновщика (например, опция «стек» для команды ld).

После запуска приложение может вызвать системную службу для выделения страниц памяти и иметь ссылку на регистр указателя стека. Затем это становится стеком программ.

Имейте в виду, что все это относится к стеку USER. Операционная система поддерживает стек KERNEL для каждого процесса, который он использует для своих целей.

Смежные вопросы