Обмін даними з призначеним для користувача процесом
Ми вже згадували, що спілкування з
призначеним для користувача процесом допустимо лише в одному з можливих
контекстів нитки ядра, а саме в призначеному для користувача. У всіх останніх
контекстах призначений для користувача процес просто не
визначений — точніше сказати, активний призначений для користувача процес
не збігається з тим процесом, запит якого в даний момент обробляється
драйвером.
У цій ситуації виклик примітивів взаємодії з цим процесом може
привести до непередбачуваних результатів.
У ряді
випадків замість драйвера цей обмін здійснюють інші модулі ял-ра, наприклад процедури
пред- і постобробки запиту. Безпосередньо з призначеним для користувача
адресним простором драйвер повинен спілкуватися лише в синхронній моделі.
У цій моделі драйвер інколи виявляється вимушений вирішувати та інші, здавалося
б невластиві йому, завдання.
Обробка сигналів драйвером в Unix
Так, в системах сімейства Unix всі операції введення-виводу, а також всі
останні операції, що переводять процес в стан чекання, можуть
бути перервані сигналом. Сигнал є примітивом обробки виключень,
частково схожий на апаратне переривання тим, що при обробці сигналу
може бути викликана надана програмістом функція-обробник. Необроблений
сигнал зазвичай наводить до примусового завершення процесу.
Будучи перерваний
сигналом, системний виклик зупиняє поточну операцію, і, якщо
це була операція обміну даними, але даних передано не було, повертає код
помилки EINTR, що говорить про те, що виклик був перерваний і, можливо,
операцію слід повторити. Код, що робить це, присутній
в прикладі 10.1.
Наприклад,
призначений для
користувача процес може використовувати сигнал SIGALARM для
того, щоб встановити свій власний будильник, що сигналізує,
що операція над пристроєм виконується підозріло довго.
Якщо драйвер не встановить свого будильника і не стане відпрацьовувати сигнали,
послані процесу, може виникнути дуже неприємна ситуація.
Річ
у тому, що в Unix всі сигнали, у тому числі і сигнал безумовного вбивства
SIGKILL, обробляються процедурою постобробки системного виклику. Якщо
драйвер не передає управління процедурі обробки поста, то і сигнал,
відповідно, виявляється необробленим, тому процес залишається висіти.
Інших
засобів, окрім посилки сигналу, для знищення процесу в системах сімейства
Unix не передбачено. Тому процес, що завис усередині звернення
до драйвера, виявляється неможливо припинити ні зсередини, ні ззовні.
Автор зіткнувся з цим
при експлуатації багатопроцесорної версії системи SCO Open Desktop 4.0.
Система була забезпечена стрічкопротяжним пристроєм, що підключається до зовнішньої
SCSI-шине. Із-за апаратних проблем цей пристрій інколи "зависав", припиняючи
відповідати на запити системи. Драйвер лен-топротяжки інколи правильно
відпрацьовував цей стан як апаратну помилку, а інколи
теж впадав в ступор, не прокидаючись ні по власному будильнику, ні по
сигналах, посланих іншими процесами. (По відомостях, що є у
автора, ця проблема специфічна саме для багатопроцесорної версії системи.
Мабуть, це означає, що помилка допущена не в драйвері, а в
коді сервісних функцій.) В результаті процес, що звертався в цей час
клеїте, також намертво зависав, і від нього не можна було позбавитися.
Із-за наявності невбиваного процесу виявлялося неможливо виконати
нормальне закриття системи; зокрема, не виходило размонтировать файлові системи,
де завислий процес мав відкриті файли. Виконання холодного перезавантаження
системи з неразмонтированными файловими томами
Введення в операційні систем
наводило до неприємних наслідків для цих томів. Одна з аварій, до
до торым це привело, детально описується в разд. Відновлення
ФС після збою.
|