стек ядра и стек пользовательского пространства


в чем разница между стеком ядра и пользовательским стеком? Почему используется стек ядра? Если локальная переменная объявлена в ISR, где она будет храниться? Каждый процесс имеет свой собственный стек ядра ? Тогда как процесс координируется между обоими этими стеками?

3 79

3 ответа:

  1. в чем разница между стеком ядра и пользовательским стеком ?

короче говоря, ничего-кроме использования другого места в памяти (и, следовательно, другого значения для регистра stackpointer), и обычно разные защиты доступа к памяти. Т. е. при выполнении в пользовательском режиме память ядра (частью которой является стек ядра) будет недоступна даже при отображении. Наоборот, без явного запроса со стороны код ядра (в Linux, через такие функции, как copy_from_user()), пользовательская память (включая пользовательский стек) обычно не доступна напрямую.

  1. почему используется [отдельный ] стек ядра ?

Разделение привилегий и безопасности. Во-первых, программы пользовательского пространства могут делать свой стек(указатель) все, что они хотят, и обычно нет архитектурного требования даже иметь действительный. Поэтому ядро не может доверие пользовательское пространство stackpointer, чтобы быть действительным и не использовать, и поэтому потребуется один набор под своим собственным контролем. Различные архитектуры ЦП реализуют это по - разному; процессоры x86 автоматически переключают stackpointers при переключении режима привилегий, а значения, используемые для разных уровней привилегий, настраиваются-по привилегированному коду (т. е. только ядро).

  1. если локальная переменная объявлена в ISR, где она будет хранится ?

в стеке ядра. Ядро (то есть ядро Linux) делает не hook ISRs непосредственно к архитектуре x86 прерывание ворота но вместо этого делегирует отправку прерывания общему механизму входа/выхода прерывания ядра, который сохраняет состояние регистра перед прерыванием перед вызовом зарегистрированного обработчика(ов). Сам ЦП при отправке прерывания может выполнять привилегию и / или переключатель стека, и это используется / настраивается ядром так, чтобы общий код ввода прерывания уже мог полагаться на наличие стека ядра.
Тем не менее, прерывания, которые происходят во время выполнения кода ядра, будут просто (продолжать) использовать стек ядра на месте в этот момент. Это может, если обработчики прерываний имеют глубоко вложенные пути вызова, привести к переполнению стека (если глубокий путь вызова ядра прерывается, а обработчик вызывает другой глубокий путь; в Linux файловая система / программный код RAID прерывается сетевой код с активными iptables, как известно, запускает такие в не настроенных старых ядрах ... решение заключается в увеличении размеров стека ядра для таких рабочих нагрузок).

  1. каждый процесс имеет свой собственный стек ядра ?

не только каждый процесс-каждый thread имеет свой собственный стек ядра (и, по сути, свой собственный стек пользователей). Помните, что единственное различие между процессами и потоками (для Linux) - это факт что несколько потоков могут совместно использовать адресное пространство (создание процесса).

  1. как процесс координируется между обоими этими стеками ?

вовсе нет - это и не нужно. Планирование (как / когда выполняются различные потоки, как их состояние сохраняется и восстанавливается) является задачей операционной системы, и процессы не должны беспокоиться об этом. Как создаются потоки (и каждый процесс должен иметь хотя бы один поток), ядро создает стеки ядра для них, в то время как стеки пространства пользователей либо явно создаются/предоставляются любым механизмом, используемым для создания потока (функции, такие как makecontext() или pthread_create() разрешить вызывающему указать область памяти, которая будет использоваться для стека" дочернего " потока) или наследуется (путем клонирования памяти при доступе, обычно называемого "копировать при записи" / COW, при создании нового процесса).
Тем не менее, процесс можете влияние планирования его потоков и / или влиять на контекст (состояние, среди которого есть stackpointer потока). Существует несколько способов для этого: UNIX сигналы,setcontext(),pthread_yield()/pthread_cancel(), ... - но это немного отталкивает от первоначального вопроса.

мой ответ собран из других вопросов SO с моими материалами.

What's the difference between kernel stack and user stack?

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

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

http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-10/3194.html

Why kernel stack is used?

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

http://www.kernel.org/doc/Documentation/x86/kernel-stacks

If a local variable is declared in an ISR, where it will be stored?

он будет храниться в ISR стек (IRQSTACKSIZE). ISR работает на отдельном стеке прерываний только в том случае, если его поддерживает аппаратное обеспечение. В противном случае кадры стека ISR помещаются в стек прерванного потока.

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

 Does each process has its own kernel stack ?

да. Каждый процесс имеет свое ядро стек.

 Then how the process coordinates between both these stacks?

@FrankH ответ выглядит здорово для меня.

  1. в чем разница между стеком ядра и пользовательским стеком

принимая во внимание ссылку на разработку ядра Linux Роберта Лав, основное различие заключается в размере:

User-space может уйти со статическим распределением многих переменных в стеке, в том числе огромные структуры и массивы из тысяч элементов.
Это поведение является законным, потому что пользовательское пространство имеет большой стек, который может динамически расти.
Стек ядра не является ни большим, ни динамическим; он мал и фиксирован по размеру.
Точный размер стека ядра зависит от архитектуры.
На x86, размер стека настраивается на время компиляции и может быть либо 4KB или 8KB.
Исторически стек ядра состоит из двух страниц, что обычно подразумевает, что это 8KB на 32-битных архитектурах и 16KB на 64-битных архитектурах-это размер является фиксированным и абсолютным.
Каждый процесс получает свой собственный стек.

также стек ядра содержит указатель на структуру struct thread_info информацией о нити.