it-swarm.com.ru

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

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

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

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

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

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

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

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

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

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

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

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

162
FrankH.

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

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

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

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

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 мне кажется великолепным.

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

Если взять ссылку из Linux Kernel Development Роберта Лава, то основным отличием является размер:

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

Также стек ядра содержит указатель на структуру thread_info, содержащую информацию о потоке.

3
arenard