Відповіді:
- Яка різниця між стеком ядра та стеком користувача?
Коротше кажучи, нічого - крім використання іншого місця в пам'яті (а значить, і іншого значення для реєстру стекпоінтера), і зазвичай різних захистів доступу до пам'яті. Тобто при виконанні в користувальницькому режимі пам’ять ядра (частиною якого є стек ядра) не буде доступною, навіть якщо їх відображено. І навпаки, без явного запиту коду ядра (в Linux через такі функції copy_from_user()
), як правило, пам'ять користувача (включаючи стек користувача) зазвичай не доступна безпосередньо.
- Чому використовується [окремий] стек ядра?
Поділ пільг та безпеки. Для одного, програми простору користувачів можуть робити свій стек (покажчик) все, що завгодно, і зазвичай немає архітектурних вимог навіть мати дійсну. Тому ядро не може довіряти стек-покажчику простору користувача, щоб воно було дійсним чи корисним, і тому буде потрібно один набір під його власним контролем. Різні архітектури процесора реалізують це по-різному; Процесори x86 автоматично перемикають стек-покажчики, коли трапляються перемикачі режиму привілеїв, і значення, що використовуються для різних рівнів привілеїв, можна налаштувати - за допомогою привілейованого коду (тобто лише ядра).
- Якщо локальна змінна оголошена в ISR, де вона буде зберігатися?
На стеку ядра. Ядро (Linux ядро, тобто) не підключає ISR безпосередньо до воріт переривання архітектури x86, а замість цього делегує пересилку переривання загальним механізмом входу / виходу з переривання ядра, який зберігає стан реєстрації попереднього переривання перед викликом зареєстрованого обробника (ів) . Сам процесор при відправленні переривання може виконати привілей та / або стек-комутатор, і це використовується / налаштоване ядром, щоб загальний код запису переривання вже міг покладатися на наявний стек ядра.
Однак, переривання, які виникають під час виконання коду ядра, просто (продовжують) використовувати стек ядра на місці в цій точці. Це може, якщо обробники переривань мають глибоко вкладені шляхи викликів, призвести до переповнення стека (якщо глибокий шлях виклику ядра перерваний і обробник викликає ще один глибокий шлях; в Linux, RAID-код файлової системи та програмного забезпечення переривається мережевим кодом з активним iptables Відомо, що він запускає такі у ненутованих старих ядрах ... рішення полягає в збільшенні розміру стека ядра для таких навантажень).
- Чи має кожен процес власний стек ядра?
Не тільки кожен процес - кожен потік має власний стек ядра (і, власне, також власний стек користувача). Пам'ятайте, що єдиною відмінністю між процесами та потоками (для Linux) є те, що декілька потоків можуть ділити адресний простір (утворюючи процес).
- Як процес координує обидва ці стеки?
Зовсім не - це не потрібно. Планування (як / коли запускаються різні потоки, як зберігається і відновлюється їх стан) - це завдання операційної системи і процесам не потрібно цим займатися. Оскільки нитки створюються (і кожен процес повинен мати принаймні один потік), ядро створює для них стеки ядер, тоді як стеки простору користувачів або явно створюються / надаються залежно від того, який механізм використовується для створення потоку (функції, як makecontext()
або pthread_create()
дозволяють абоненту вкажіть область пам’яті, яка буде використовуватись для стека «дочірнього» потоку) або успадкована (шляхом клонування пам’яті під час доступу, зазвичай її називають «копіювати при записі» / COW, під час створення нового процесу).
Це сказав:(стан, серед якого є стек-покажчик потоку). Є кілька способів для цього: сигналів UNIX, setcontext()
, pthread_yield()
/ pthread_cancel()
, ... - але це disgressing трохи від початкового питання.
Моя відповідь зібрана з інших запитань ТА з моїми матеріалами.
What's the difference between kernel stack and user stack?
Як програміст ядра, ви знаєте, що ядро повинно бути обмежене помилковими програмами користувача. Припустимо, ви зберігаєте однаковий стек як для ядра, так і для користувальницького простору, а потім простий сегмент за замовчуванням в програмі користувача вибиває ядро і потребує перезавантаження.
Існує один "стек ядра" на процесор, як ISR Stack і один "стек ядра" на Process. Існує один "стек користувача" для кожного процесу, хоча кожен потік має свій стек, включаючи і потоки користувача, і ядра.
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 мені прекрасно виглядає.
- Яка різниця між стеком ядра та стеком користувача
Посилаючись на розробку Linux ядра Роберта Лава, головна відмінність - розмір:
Користувальницький простір може позбутися статичного розподілу багатьох змінних на стеку, включаючи величезні структури та масиви тисяч елементів.
Така поведінка є законною, оскільки у просторі користувача є великий стек, який може динамічно зростати.
Стек ядра не є ні великим, ні динамічним; вона невелика і зафіксована в розмірах.
Точний розмір стека ядра залежить від архітектури.
На x86 розмір стека може бути налаштований під час компіляції і може становити 4 КБ або 8 КБ.
Історично стек ядра становить дві сторінки, що, як правило, означає, що він становить 8 КБ для 32-бітових архітектур і 16 КБ для 64-бітових архітектур - цей розмір є фіксованим і абсолютним.
Кожен процес отримує свій стек.
Також стек ядра містить вказівник на структуру потоку_info, що містить інформацію про потік.