7.3.8 Асинхронный ввод-вывод |
Предыдущая Содержание Следующая |
Традиционные системные вызовы чтения и записи являются блокирующими вызовами. Большинство приложений реального времени может нуждаться в прерывании их работы и процесса ввода/вывода с целью улучшения детерминизма. Например, приложение может предпочесть асинхронный ввод/вывод (Asynchronous I/O, AIO), если требуется сбор большого объёма данных от какого-то источника и если обработка данных - интенсивное вычисление. POSIX.1b определяет асинхронные интерфейсы ввода/вывода для выполнения требований таких приложений. Механизм очень прост. Приложение может поместить в очередь запрос на AIO, а затем продолжить нормальную обработку. По завершении ввода/вывода приложение уведомляется. Затем оно может запросить состояние ввода/вывода, чтобы узнать был ли он успешным или закончился неудачей. Используя интерфейсы AIO, приложение может выполнять следующие операции:
▪Формировать нескольких неблокирующих запросов ввода/вывода для различных источников с помощью единственного вызова. (Таким образом, приложение может иметь много операций ввода/вывода в процессе выполнения, в то время как оно выполняет другой код.) ▪Отменять любые не выполненные запросы ввода/вывода. ▪Ожидать завершения ввода/вывода. ▪Отслеживать состояние ввода/вывода: в процессе работы, ошибка, или завершён.
Блок управления асинхронным вводом-выводом
Блок управления AIO, структура aiocb, является ядром AIO POSIX.1b. Эта структура содержит сведения, которые необходимы для представления AIO. Структура определяется следующим образом:
struct aiocb { int aio_fildes; /* Файловый дескриптор. */ int aio_lio_opcode; /* Операция для выполнения, чтение или запись. Используется при нескольких запросах AIO в одном запросе */ int aio_reqprio; /* Изменение приоритета запроса. */ volatile void *aio_buf; /* Расположение буфера для чтения или записи */ size_t aio_nbytes; /* Размер передачи. */ struct sigevent aio_sigevent; /* Информация уведомления. */ off_t aio_offset; /* Смещение в файле для начала чтения или записи в него */ }
Обратите внимание, что в отличие от традиционных операций чтения или записи, вам необходимо указать смещение в файле, откуда должен начаться AIO. После выполнения ввода/вывода ядро не будет увеличивать значение поля, содержащее смещение в файле, в файловом дескрипторе. Вы должны следить за смещениями в файле вручную.
Функции асинхронного ввода-вывода
Функции AIO приведены в Таблице 7.11. Использование интерфейсов AIO POSIX.1b иллюстрирует Распечатка 7.12. Этот пример просто копирует один файл в другой с помощью AIO. Для простоты будем считать, что функции AIO не возвращают ошибку.
Таблица 7.11 Функции асинхронного ввода-вывода
Ввод/вывод, направляемый в список
Для передачи произвольного числа запросов чтения или записи в одном вызове может быть использована функция lio_listio:
int lio_listio(int mode, struct aiocb *list[], int nent, struct sigevent *sig);
▪mode: этот аргумент может быть LIO_WAIT или LIO_NOWAIT. Если этот аргумент имеет значение LIO_WAIT, функция ждёт, пока все вводы-выводы завершатся и sig игнорируется. Если аргументом является LIO_NOWAIT, функция возвращается немедленно и после завершения ввода/вывода будет происходить асинхронное уведомление, как указано в sig. ▪Список aiocb: этот аргумент содержит список aiocb. ▪nent: количество aiocb во втором аргументе. ▪sig: желаемый механизм уведомления. Уведомление не генерируется, если этот аргумент NULL.
Распечатка 7.12 может быть изменена для использования функции lio_listio.
while(1){ memcpy(write_buf, read_buf, read_n); a_write.aio_nbytes = read_n; a_read.aio_nbytes = XFER_SIZE;
/* Готовим список aiocb для lio_listio */ cblist_lio[0] = &a_read; cblist_lio[1] = &a_write;
/* * Вызываем lio_listio, чтобы отправить запросы * асинхронного чтения и записи */ lio_listio(LIO_NOWAIT, cblist_lio, 2, NULL); …………… }
Реализация в Linux
Первоначально AIO в Linux был полностью реализован в пользовательском пространстве с помощью потоков. Был один пользовательский поток, создаваемый для каждого запроса. Это привело к плохой масштабируемости и низкой производительности. Начиная с версии 2.5, в ядро была добавлена поддержка AIO. Тем не менее, интерфейсы ядра, предоставляющие AIO, отличаются от интерфейсов POSIX. Интерфейсы базируются на новом наборе системных вызовов. Они перечислены в Таблице 7.12. Эти интерфейсы предоставляются в пользовательском пространстве библиотекой libaio.
Таблица 7.12 Интерфейсы асинхронного ввода-вывода в ядре
Что следует помнить
▪Блок управления не должен изменяться во время выполнения операции чтения или записи. Также, указатель буфера в aiocb должен быть действителен, пока запрос не завершен. ▪Возвращаемое значение lio_listio не указывает состояние отдельных запросов ввода/вывода. Неудачное завершение запроса не препятствует завершению других запросов.
| ||||||||||||||||||||||||||||||
Предыдущая Содержание Следующая |