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

111

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

jkv
источник

Ответы:

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

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

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

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

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

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

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

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

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

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

FrankH.
источник
Отличные ответы FrankH. Спасибо.
kumar
1
@FrankH Отличный ответ .. но у меня есть небольшие вопросы, связанные с этим, но в архитектуре ARM .. Как этот стек ядра связан с другим режимом процессора?
Рахул
2
@Rahul: «поле для SO-комментария слишком мало, чтобы содержать такой ответ». Как стеки / регистры стекового указателя работают в различных режимах ЦП ARM (которые реализуют банковскую SP) - хороший вопрос, но для ответа требуется больше места, чем может дать комментарий. То же самое относится к таким вещам, как шлюзы задач x86 или IST - не существует такой вещи, как «единый» указатель стека ядра (точно так же, как нет «единственного» указателя стека пользователя), и какая аппаратная поддержка / мандат существует для отдельные указатели стека в разных режимах работы ... очень зависят от оборудования.
Фрэнк Х.
@FrankH. Я создал новый вопрос для того же ... stackoverflow.com/q/22601165/769260 Надеюсь, теперь вы можете помочь мне, не заботясь о пространстве :)
Рахул
1
@FrankH. Можете ли вы предоставить диаграмму, показывающую, где находится стек ядра в структуре памяти процесса?
Джитин Павитран
19

Мой ответ собран из других вопросов 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 мне нравится.

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

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

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

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

аренард
источник