Синхронне уведення-виведення
Найпростішим механізмом виклику функцій драйвера був би непрямий виклик відповідних
процедур, складових тіло драйвера, подібно до того, як
це робиться в MS DOS і ряду інших однозадачних систем.
У системах сімейства Unix драйвер послідовного пристрою виконується
в рамках тієї нитки, яка сформувала запит, хоча і з привілеями
ядра. Чекаючи реакції пристрою, драйвер переводить процес в стан
чекання доступними йому примітивами роботи з планувальником. У прикладі
10.1 це interruptibie_sieep_on. Як параметр
цієї функції передається блок змінних стану пристрою, і
в цьому блоці зберігається заслання на контекст нитки, що блокується.
Доступні прикладним програмам функції
драйвера виконуються в призначеному для користувача контексті —
в тому сенсі, що, хоча драйвер і працює в адресному просторі ядра, але
при його роботі визначений і призначений для користувача адресний простір,
тому він може користуватися примітивами
Обміну даними З НИМ (у прикладі 10.1 це memcpy_from_fs).
Обробник переривання навпаки працює
в контексті переривання, коли призначений для користувача адресний
простір не визначений. Тому, аби при обслуговуванні переривання
можна було дістати доступ до призначених для користувача
даних, основна нитка драйвера вимушена копіювати їх в буфер в адресному
просторі ядра.
Синхронна модель драйвера дуже проста в реалізації, але має
істотний недолік, приведений в прикладі 10.1, — драйвер нереєнтерабельний.
Звернення двох ниток до одного пристрою приведе до непередбачуваних
наслідків (втім, для практичних цілей досить того, що серед
можливих наслідків числиться порушення цілісності даних і подальша
паніка регістрів на екрані). Передбаченість наслідків забезпечується
включенням в контекст пристрою семафора, установкою цього семафора при вході
у функцію foo_write і зняттям його при виході. Семафор має чергу
чекаючих його процесів, і, таким чином, реентрантно (тобто під час обробки
попереднього аналогічного запиту) запити, що приходять, встановлюватимуться
в чергу.
Альтернативний підхід
до організації введення-виводу полягає в тому, аби покласти роботу по
формуванню черги запитів не на драйвер, а на функцію передобробки запиту.
При цьому перший запит до драйвера, що деякий час був неактивним, може як
і раніше здійснюватися в нитці процесу, що сформував цей запит, але все
подальші запити витягуються з черги fork-процессом драйвера при завершенні
попереднього запиту. Такий підхід називається асинхронним.
Примітка
Тут
виникає цікаве питання: якщо запит обробляється асихронно, то
чи зобов'язана призначена для користувача програма чекати закінчення операції?
Взагалі кажучи, не зобов'язана, але це питання детальніше обговорюватиметься в разд.
Асинхронна модель введення-виводу з точки зору додатків.
|