Поговорим подробнее об одном важном различии между способами ввода/вывода по опросу готовности и по прерываниям.
Основной особенностью ввода/вывода по опросу готовности является цикл ожидания. Если выполняется ввод или вывод на медленное устройство (например, матричный принтер), то этот скромно выглядящий цикл будет занимать, мягко говоря, 99% всего времени работы процессора. Если происходит ожидание ввода с клавиатуры, то процессор вообще не будет делать ничего полезного, пока пользователь не удосужится нажать клавишу.
Такое абсурдное использование процессора может быть оправдано разве что в том случае, если для него нет никакой более полезной работы. Это возможно в случае однозадачной ОС, когда работающая прикладная программа не может продвигаться дальше, пока не завершена операция ввода/вывода. В этом случае ввод/вывод по опросу не лишен определенных достоинств: он не связан с обработкой прерываний, которая требует некоторого времени, а потому замедляет реакцию на переход устройства в состояние готовности.
Способ ожидания программой некоторого события, основанный на постоянной циклической проверке ожидаемого условия, называется активным ожиданием (busy waiting). Это понятие применяется не только по отношению к вводу/выводу, но и во многих других ситуациях, возникающих при работе системных и прикладных программ.
Если рассматривается многозадачная ОС, в которой может быть несколько активных задач одновременно, то активное ожидание становится совершенно неприемлемым. В этом случае расход процессорного времени на выполнение циклического опроса наносит прямой ущерб другим программам, которые могли бы использовать это время более осмысленно. Поэтому при разработке многозадачных систем, как при вводе/выводе, так и в некоторых других ситуациях, обязательно реализуется пассивное ожидание, т.е. такая реализация ожидания, при которой ожидающая программа не затрачивает процессорного времени. Для реализации пассивного ожидания всегда в той или иной форме используются аппаратные прерывания. Частным примером пассивного ожидания является рассмотренный выше ввод/вывод по прерываниям.
Синхронный и асинхронный ввод/вывод
Программист, разрабатывающий прикладные программы, не должен думать о таких вещах, как способ работы системных программ с регистрами устройств. Система скрывает от приложений детали низкоуровневой работы с устройствами. Однако различие между организацией ввода/вывода по опросу и по прерываниям находит определенное отражение и на уровне системных функций, в виде функций для синхронного и асинхронного ввода/вывода.
Выполнение функции синхронного ввода/вывода включает в себя запуск операции ввода/вывода и ожидание завершения этой операции. Только после завершения ввода/вывода функция возвращает управление вызвавшей программе.
Синхронный ввод/вывод — это наиболее привычный для программистов способ работы с устройствами. Стандартные процедуры ввода/вывода языков программирования работают именно таким способом.
Вызов функции асинхронного ввода/вывода означает только запуск соответствующей операции. После этого функция сразу возвращает управление вызвавшей программе, не дожидаясь завершения операции.
Рассмотрим, например, асинхронный ввод данных. Понятно, что программа не может обращаться к данным, пока нет уверенности, что их ввод завершен. Но вполне возможно, что программа может пока что заняться другой работой, а не простаивать в ожидании.
Рано или поздно программа все-таки должна приступить к работе с введенными данными, но предварительно убедиться, что асинхронная операция уже завершилась. Для этого различные ОС предоставляют средства, которые можно разбить на три группы.
· Ожидание завершения операции. Это как бы «вторая половина синхронной операции». Программа сначала запустила операцию, потом выполнила какие-то посторонние действия, а теперь ждет окончания операции, как при синхронном вводе/выводе.
· Проверка завершения операции. При этом программа не ожидает, а только проверяет состояние асинхронной операции. Если ввод/вывод еще не завершен, то программа имеет возможность еще какое-то время погулять.
· Назначение процедуры завершения. В этом случае, запуская асинхронную операцию, программа пользователя указывает системе адрес пользовательской процедуры или функции, которая должна быть вызвана системой после завершения операции. Сама программа может больше не интересоваться ходом ввода/вывода, система напомнит ей об этом в нужный момент, вызвав указанную функцию. Этот способ наиболее гибкий, поскольку в процедуре завершения пользователь может предусмотреть любые действия.
В Windows прикладной программе доступны все три способа завершения асинхронных операций. В UNIX асинхронных функций ввода/вывода нет, однако тот же эффект асинхронности может быть достигнут иначе, путем запуска дополнительного процесса.
Асинхронное выполнение ввода/вывода позволяет в некоторых случаях повысить производительность работы и обеспечить дополнительные функциональные возможности. Без такой простейшей формы асинхронного ввода, как «ввод с клавиатуры без ожидания», были бы невозможны многочисленные компьютерные игры и тренажеры. В то же время логика программы, использующей асинхронные операции, сложнее, чем при синхронных операциях.