Витіснення і перемикання контексту

Перемикання контексту – це переключення від однієї, готової до виконання задачі до іншої Це перемикання проводиться за допомогою функції context_switch (), визначеної у файлі kernel / schedс Дана функція викликається функцією schedule (), коли новий процес вибирається для виконання При цьому виконуються наступні кроки

• Викликається функція switch_mm (), яка визначена у файлі include / asm / mmu_contexth і призначена для перемикання від віртуальної памяті старого процесу до віртуальної памяті нового процесу

• Викликається функція switch_t o (), визначена у файлі includ e / asm / systemh, для перемикання від стану процесора попереднього процесу до стану процесора нового процесу Ця процедура включає відновлення інформації стека ядра і регістрів процесора

Ядро повинне мати інформацію про те, коли викликати функцію schedul e () Якщо ця функція буде викликатися тільки тоді, коли програмний код викликає її явно, то для користувача програми можуть виконуватися невизначений час Тому ядро ​​підтримує прапор need_resched для того, щоб сигналізувати, чи необхідно викликати функцію schedul e () (табл 42) Цей прапор встановлюється функцією schediiler_tic k (), коли процес істрачівает свій квант часу, і функцією try_to_wake_up (), коли процес з пріоритетом більш високим, ніж у поточного процесу, повертається до виконання Ядро перевіряє значення цього прапора, і якщо він встановлений, то викликається функція schedule () для перемикання на новий процес Цей прапор є повідомленням ядру про те, що планувальник повинен бути активізований по можливості раніше, тому що інший процес повинен розпочати виконання

Таблиця 42 Функції для управління прапором need_resche d

Функція Призначення

set_tsk_need_resched (task) Встановити прапор need_resched для даного процесу

clear_tsk_need_resched (task) Очистити прапор need_resched для даного процесу

need_resched () Перевірити значення прапора need_resched для даного процесу Повертається значення true, якщо цей прапор встановлений, і false, якщо не встановлено

Під час перемикання в простір користувачі або при поверненні з переривання, значення прапора need_resched перевіряється Якщо він встановлений, то ядро ​​активізує планувальник перед тим, як продовжити роботу

Цей прапор не є глобальної змінної, так як звернення до дескриптора процесу виходить більш швидким, ніж звернення до глобальних даними (через швидкість звернення до змінної curren t і тому, що відповідні дані можуть знаходитися в кеші) Історично, цей прапор був глобальним в ядрах до серії

22 У ядрах серій 22 і 24 цей прапор належав структурі task_struc t і мав тип int У серії ядер 26 цей прапор переміщений в один певний біт спеціальної змінної прапорів структури threa d info Легко бачити, що розробники ядра ніколи не можуть бути всім задоволені

Витіснення простору користувача

Витіснення простору користувача (user preemption) відбувається в той момент, коли ядро ​​збирається повернути управління режиму користувача, при цьому встановлюється прапор need_resched і, відповідно, активізується планувальник Коли ядро ​​повертає управління в простір користувача, то воно знаходиться в безпечному і спокійному стані Іншими словами, якщо продовження виконання поточного завдання є безпечним, то безпечним буде також і вибір нового завдання для виконання Тому коли ядро ​​готується повернути управління в режим користувача або при поверненні з переривання або після системного виклику, відбувається перевірка прапора need_resched Якщо цей прапор встановлений, то активізується планувальник І вибирає новий, більш відповідний процес для виконання Як процедура повернення з переривання, так і процедура повернення з системного виклику є залежними від апаратної платформи і зазвичай реалізуються на мові асемблера у файлі entry S (цей файл, крім коду входу в режим ядра, також містить і код виходу з режиму ядра) Якщо коротко, то витіснення простору користувача може статися в наступних випадках

• При поверненні в простір користувача з системного виклику

• При поверненні в простір користувача з обробника переривання

Витіснення простору ядра

Ядро операційної системи Linux, на відміну від ядер більшості варіантів ОС Unix, є повністю преемптівним (витісняється, preemptible) У непреемптівних ядрах код ядра виконується до завершення Іншими словами, планувальник не може здійснити планування для виконання іншого завдання, поки якесь завдання виконується в просторі ядра – код ядра планується на виконання кооперативно, а не за допомогою витіснення Код ядра виконується доти, поки він не завершиться (поверне управління в простір користувача) або поки явно не заблокується З появою серії ядер 26, ядро Linux стало преемптівним: тепер є можливість витіснити завдання в будь-який момент, звичайно, поки ядро ​​знаходиться в стані, коли безпечно проводити перепланування виконання

У такому випадку коли ж безпечно проводити перепланування Ядро здатне витіснити завдання, яке працює в просторі ядра, коли це Завдання не утри-

живає блокування Іншими словами, блокування використовуються в якості маркерів тих областей, в які завдання не може бути витіснене Ядро розраховане на багатопроцесорність (SMP-safe), тому якщо блокування не утримується, то код ядра є реєнтерабельним і його витісняти безпечно

Перша зміна, внесена для підтримки витіснення простору ядра, – це введення лічильника преемптівності preempt_coun t в структуру thread_inf про кожного процесу Значення цього лічильника спочатку дорівнює нулю і збільшується на одиницю при кожному захопленні блокування, а також зменшується на одиницю при кожному звільнення блокування Коли значення лічильника дорівнює нулю-ядро є витісняється При поверненні з обробника переривання, якщо повернення виконується в простір ядра, ядро ​​перевіряє значення змінних need_resche d і preempt_count Якщо прапор need_resche d встановлений і значення лічильника preempt__coun t дорівнює нулю, значить, більш важливе завдання готове до виконання і виконувати витіснення безпечно Далі активізується планувальник Якщо значення лічильника preempt_coun t не дорівнює нулю, значить, утримується захоплена блокування і виконувати витіснення небезпечно У такому випадку повернення з обробника переривання відбувається в поточне виконувати завдання Коли звільняються всі блокування, утримувані поточним завданням, значення лічильника preempt_coun t стає рівним нулю При цьому код, який здійснює звільнення блокування, перевіряє, чи не встановлений прапор need_resched Якщо встановлено, то активізується планувальник Іноді коду ядра необхідно мати можливість забороняти або дозволяти витіснення в режимі ядра, що буде розглянуто в розділі 9

Витіснення простору ядра також може статися явно, коли завдання блокується в режимі ядра або явно викликається функція schedul e () Така форма преемптівності ядра завжди підтримувалася, так як в цьому випадку немає необхідності в додатковій логіці, яка б давала можливість переконатися, що витіснення проводити безпечно Передбачається, що якщо код явно викликає функцію schedul e (), то точно відомо, що перепланування виробляти безпечно

Витіснення простору ядра може відбутися в наступних випадках

• При поверненні з обробника переривання в простір ядра

• Коли код ядра знову стає преемптівним

• Якщо завдання, що працює в режимі ядра, явно викликає функцію schedul e ()

• Якщо завдання, що працює в режимі ядра, переходить в призупинене стан, тобто блокується (що призводить до виклику функції schedul e ())

Джерело: Лав, Роберт Розробка ядра Linux, 2-е видання : Пер з англ – М: ТОВ «ІД Вільямс »2006 – 448 с : Ил – Парал тит англ

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*