Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Примечание






В действительности, не все так просто. read(2) действительно должен ожидать физического прочтения данных с устройства, но write(2) по умолчанию работает в режиме отложенной записи: он возвращает управление после того, как данные переданы в системный буфер, но, вообще говоря, до того, как данные будут физически переданы устройству. Это, как правило, значительно повышает наблюдаемую производительность программы и позволяет использовать память из-под данных для других целей сразу после возврата write(2). Но отложенная запись имеет и существенные недостатки. Главный из них – вы узнаете о результате физической операции не сразу по коду возврата write(2), а лишь через некоторое время после возврата, обычно по коду возврата следующего вызова write(2). Для некоторых приложений – для мониторов транзакций, для многих программ реального времени и др. – это неприемлемо и они вынуждены выключать отложенную запись. Это делается флагом O_SYNC, который может устанавливаться при открытии файла и изменяться у открытого файла вызовом fcntl(2). Синхронизация отдельных операций записи может быть обеспечена вызовом fsync(2).

Для многих приложений, работающих с несколькими устройствами и/или сетевыми соединениями синхронная модель неудобна. Работа в режиме опроса тоже не всегда приемлема. Дело в том, что select(3С) и poll(2) считают дескриптор файла готовым для чтения только после того, как в его буфере физически появятся данные. Но некоторые устройства начинают отдавать данные только после того, как их об этом явно попросят.

Также, для некоторых приложений, особенно для приложений реального времени важно знать точный момент начала поступления данных. Для таких приложений также может быть неприемлемо то, что select(3C) и poll(2) считают регулярные файлы всегда готовыми для чтения и записи. Действительно, файловая система читается с диска и хотя она работает гораздо быстрее, чем большинство сетевых соединений, но все-таки обращения к ней сопряжены с некоторыми задержками. Для приложений жесткого реального времени эти задержки могут быть неприемлемы – но без явного запроса на чтение файловая система данные не отдает!

С точки зрения приложений жесткого реального времени может оказаться существенным еще один аспект проблемы ввода/вывода. Дело в том, что приложения жесткого РВ имеют более высокий приоритет, чем ядро, поэтому исполнение ими системных вызовов – даже неблокирующихся! – может привести к инверсии приоритета.

Решение этих проблем известно давно и называется асинхронный ввод/вывод. В этом режиме системные вызовы ввода/вывода возвращают управление сразу после формирования запроса к драйверу устройства, как правило, даже до того, как данные будут скопированы в системный буфер. Формирование запроса состоит в установке записи (IRP, Input/Output Request Packet, пакет запроса ввода вывода) в очередь. Для этого надо лишь ненадолго захватить мутекс, защищающий «хвост» очереди, поэтому проблема инверсии приоритета легко преодолима. Для того, чтобы выяснить, закончился ли вызов, и если закончился, то чем именно, и можно ли использовать память, в которой хранились данные, предоставляется специальный API (см. рис. 1)

Рис. 1. Асинхронная модель ввода/вывода

Асинхронная модель была основной моделью ввода/вывода в таких ОС, как DEC RT-11, DEC RSX-11, VAX/VMS, OpenVMS. Эту модель в той или иной форме поддерживают практически все ОС реального времени. В системах семейства Unix с конца 1980х использовалось несколько несовместимых API для асинхронного ввода/вывода. В 1993 году ANSI/IEEE был принят документ POSIX 1003.1b, описывающий стандартизованный API, который мы и изучим далее в этом разделе.

Функции aio_read(3AIO), aio_write(3AIO) и lio_listio(3AIO)

В Solaris 10 функции асинхронного ввода/вывода включены в библиотеку libaio.so. Для сборки программ, использующих эти функции, необходимо использовать ключ –laio.

Для формирования запросов на асинхронный ввод/вывод используются функции aio_read(3AIO), aio_write(3AIO) и lio_listio(3AIO).

Функции aio_read(3AIO) и aio_write(3AIO) имеют единственный параметр, struct aiocb *aiocbp. Структура aiocb определена в файле < aio.h> и содержит следующие поля:

int aio_fildes – дескриптор файла

off_t aio_offset – смещение в файле, начиная с которого будет идти запись или чтение

volatile void* aio_buf – буфер, в который следует прочитать данные или в котором лежат данные для записи.

size_t aio_nbytes – размер буфера. Как и традиционный read(2), aio_read(3AIO) может прочитать меньше данных, чем было запрошено, но никогда не прочитает больше.

int aio_reqprio – приоритет запроса

struct sigevent aio_sigevent – способ оповещения о завершении запроса (рассматривается далее в этом разделе)

int aio_lio_opcode – при aio_read(3AIO) и aio_write(3AIO) не используется, используется только функцией lio_listio.

Функция lio_listio(3AIO) позволяет одним системным вызовом сформировать несколько запросов на ввод/вывод. Эта функция имеет четыре параметра:

int mode – может принимать значения LIO_WAIT (функция ждет завершения всех запросов) и LIO_NOWAIT (функция возвращает управление сразу после формирования всех запросов).

struct aiocb *list[] – список указателей на структуры aiocb с описаниями запросов. Запросы могут быть как на чтение, так и на запись, это определяется полем aio_lio_opcode. Запросы к одному дескриптору исполняются в том порядке, в каком они указаны в массиве list.

int nent – количество записей в массиве list.

struct sigevent *sig – способ оповещения о завершении всех запросов. Если mode==LIO_WAIT, этот параметр игнорируется.

Библиотека POSIX AIO предусматривает два способа оповещения программы о завершении запроса, синхронный и асинхронный. Сначала рассмотрим синхронный способ.






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.