Теорія операційної системи

:: Меню ::

Головна
Представлення даних в обчислювальних системах
Машинні мови
Завантаження програм
Управління оперативною пам'яттю
Сегментна і сторінкова віртуальна пам'ять
Комп'ютер і зовнішні події
Паралелізм з точки зору програміста
Реалізація багатозадачності на однопроцесорних комп'ютерах  
Зовнішні пристрої
Драйвери зовнішніх пристроїв
Файлові системи
Безпека
Огляд архітектури сучасних ОС

:: Друзі ::

Карта сайту
 

:: Статистика ::

 

 

 

 

 

Асинхронна модель введення-виводу з точки зору додатків

У разд. Синхронне уведення-виведенняобговорюючи асинхронну модель драйвера, ми задалися питанням: чи повинне завдання, сформувавши запит на уведення-виведення, чекати його завершення? Адже система, прийнявши запит, передає його асинхронному драйверу, який ініціює операцію на зовнішньому пристрої і визволяє процесор. Сама система не чекає завершення запиту. Чи так повинне призначене для користувача завдання чекати його?
Якщо було запитано читання даних, то відповідь, на перший погляд, очевидна:
повинна. Адже якщо дані запитані, означає вони зараз будуть потрібні програмі.
Проте можна виділити буфер для даних, запитати читання, потім деякий час займатися чимось корисним, але що не відноситься до запиту, і лише до крапки, коли дані дійсно будуть потрібні, запитати систему: а чи готові дані? Якщо готові, то можна продовжувати роботу. Якщо немає, то доведеться чекати (мал. 10.9).
У багатьох застосуваннях, особливо інтерактивних або працюючих з іншими пристроями-джерелами подій, асинхронне читання виявляється єдино прийнятним варіантом, оскільки воно дозволяє завданню одночасно здійснювати обмін з декількома джерелами даних і таким чином підвищити пропускну спроможність і поліпшити час реакції на подію.

Мал. 10.9. Випереджаюче читання

При записі, здавалося б, немає необхідності чекати фізичною вершенія операції. При цьому ми отримуємо режим, відомий як відкладений запис (lazy write— "ледачий" запис, якщо переводити дослоцц0\ Проте такий режим створює дві специфічні проблеми.
По-перше, програма повинна знати, коли їй можна використовувати буфер даними для інших цілей. Якщо система копіює записувані дані з призначеного для користувача адресного простору в системний, то ця ж проблема виникає усередині ядра; усередині ядра проблема вирішується використанням багатобуферної схеми, і все відносно просто. Проте копіювання приводить до додаткових витрат часу і вимагає виділення пам'яті під буфери. Найгостріше ця проблема встає при роботі з дисковими і мережевими пристроями, з якими система обмінюється великими об'ємами даних (а мережеві пристрої ще і можуть генерувати дані несподівано). Проблема управління дисковими буферами детальніше обговорюється в разд. Дисковий кеш.
У більшості сучасних обчислювальних систем спільного призначення накладні витрати, обумовлені буферизацією запитів, відносно невеликі або принаймні вважаються прийнятними. Але в системах реального часу і вбудовуваних контроллерах, де час і об'єм оперативної пам'яті жорстко обмежені, ці витрати виявляються серйозним чинником.
Якщо ж замість системних буферів використовується відображення даних в системний адресний простір (системи з відкритою пам'яттю можна вважати виродженим випадком такого відображення), то ситуація ускладнюється. Призначене для користувача завдання повинне мати можливість дізнатися про фізичне закінчення запису, бо лише після цього буфер дійсно вільний. Фактично, програма повинна самостійно реалізувати багато-буферну схему або шукати інші виходи.
По-друге, програма повинна діждатися закінчення операції, щоб взнати, чи успішно вона закінчилася. Частина помилок, наприклад, спробу запису на пристрій, фізично не здатний виконати таку операцію, можна відловити ще в час передобробки, проте апаратні проблеми можуть бути виявлені лише на фазі виконання запиту.
Багато систем, що реалізовують відкладений запис, при виявленні апаратної помилки просто встановлюють прапор помилки в блоці управління пристроєм. Програма передобробки, виявивши цей прапор, відмовляється виконувати наступний запит. Таким чином, прикладна програма вважає запит, що помилково завершився, таким, що успішно виконався і виявляє помилку лише при одній з наступних спроб запису, що не зовсім правильно.
Інколи цю проблему можна ігнорувати. Наприклад, якщо програма зустрічає одну помилку при записі, то всього виконання програми вважається неуспіхом і на цьому закінчується. Проте у багатьох випадках, наприклад, завданнях управління промисловим або дослідницьким устаткуванням, програмі необхідно знати результат завершення операції, тому простий відкладений запис виявляється абсолютно неприйнятним.
Так або інакше, ОС, що реалізовує асинхронного виконання запитів введення-виводу, повинна мати засоби повідомити призначену для користувача програму про фізичне закінчення операції і результат цієї операції.

Синхронне і асинхронне уведення-виведення в Rsx-11 і VMS
Наприклад, в системах Rsx-11 і Vax/vms фірми DEC для синхронізації використовується прапор локальної події (local event flag). Як говорилося в разд. Семафорипрапор події в цих системах є аналогом двійкових семафорів Дейкстри, але з ним також може бути асоційована процедура AST. Системний виклик введення-виводу в цих ОС називається QIC (Queue Input/output [Request] — встановити в чергу запит введення-виводу) і має дві форми: асинхронну QIO і синхронну QIOW (Queue Input/output and Wait— встановити запит і чекати [завершення]). З точки зору підсистеми введення-виводу ці виклики нічим не відрізняються, просто при запиті QIO чекання кінця запиту виконується призначеною для користувача програмою "уручну", а при QIOW виділення прапора події і чекання його установки робиться системними процедурами пред- і обробки поста.
У ряді систем реального часу, наприклад, в Os-9 і Rt-11, використовуються аналогічні механізми.

Навпаки, більшість сучасних ОС спільного призначення не зв'язуються з асинхронними викликами і надають прикладній програмі чисто синхронний інтерфейс, тим самим вимушуючи її чекати кінця операції.
Можливо, це пояснюється ідейним впливом ОС Unix. Набор операцій введення-виводу, реалізованих в цій ОС, став загальновизнаним стандартом де-факто і основою для декількох офіційних стандартів. Наприклад, набір операцій введення-виводу в MS DOS є прямою копією Unix; крім того, ці операції входять в стандарт ANSI на системні бібліотеки мови З і стандарт POSIX.
Сучасні системи сімейства Unix дозволяють програмістові вибирати між відкладеним записом за принципом Fire And Forget (вистрілив і забув) і повністю синхронною, використовуючи виклик fcntl з відповідним кодом операції.
Якщо все-таки потрібний детальніший контроль над порядком обробки запитів, розробникам пропонується самостійно імітувати асинхронний обмін, створюючи для кожного асихронно виконуваного запиту свою нитку. Ця нитка тим або іншим способом повідомляє основну нитку про завершення операції. Для цього найчастіше використовуються штатні засоби міжпоточної взаємодії — семафори і ін. Грамотне використання ниток дозволяє створювати інтерактивні застосування з дуже високим суб'єктивним часом реакції, але за це доводиться платити ускладненням логіки програми. У Windows Nt/2000/xp існує засіб оргащ, зациі асинхронного введення-виводу — так звані порти завершення (операції) (completion ports). Проте цей засіб не підтримується в Windows 95, тому більшість розробників уникають використання портів завершення.
Синхронна модель введення-виводу проста в реалізації і використанні і, як показав досвід систем сімейства Unix і його ідейних спадкоємців, цілком адекватна більшості додатків спільного призначення. Проте, як вже було показано, вона не дуже зручна (а інколи і просто непридатна) для завдань реального часу. Слід також мати на увазі, що імітація асинхронного обміну за допомогою ниток не завжди допустима: асинхронні запити виконуються в тому порядку, в якому вони встановлювалися в чергу, а порядок здобуття управління нитками в багатозадачній середі не гарантований. Тому, наприклад, стандарт Posix.4 вимагає підтримки нарівні з нитками і засобів асинхронного обміну з викликом callback при завершенні операції.

 

:: Реклама ::

 

:: Посилання ::


 

 

 


Copyright © Kivik, 2017