Чтение онлайн

на главную - закладки

Жанры

Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform

Кёртен Роб

Шрифт:

Но на самом деле роль функции io_open гораздо значительнее. Она отвечает не только за проверку, может клиент открыть ресурс или нет, но также за следующее:

• инициализацию внутренних параметров библиотеки;

• привязку к запросу контекстного блока;

• привязку к контекстному блоку атрибутной записи.

Первые две операции выполняются с помощью функции базового уровня resmgr_open_bind, а привязка атрибутной записи сводится к простому присваиванию.

Будучи однажды вызвана, io_open выпадает из рассмотрения. Клиент может либо прислать сообщение ввода/вывода, либо нет, но в любом случае

должен будет однажды завершить «сеанс связи» с помощью сообщения, соответствующего функции close. Заметьте, что если клиента вдруг постигает внезапная смерть (например, он получает SIGSEGV, или выходит из строя узел, на котором он работает), операционная система автоматически синтезирует сообщение close, чтобы администратор ресурсов смог корректно завершить сессию. Поэтому вы гарантированно получите сообщение close!

Сообщения, которые должны быть сообщениями установления соединения, но таковыми не являются

Тут есть один интересный момент, который вы, может быть, для себя уже отметили. Прототип клиентской функции chown имеет вид:

int chown(const char *path, uid_t owner, gid_t group);

Вспомните: сообщение об установлении соединения всегда содержит имя пути и является либо однократным, либо устанавливает контекст для дальнейших сообщений ввода/ вывода.

Так почему же сообщение, соответствующее клиентской функции chown, не является сообщением установления соединения? К чему здесь сообщение ввода/вывода, когда в прототипе даже дескриптора файла нет?!

Ответ простой — чтобы облегчить вам жизнь.

Представьте себе, что было бы, если бы функции типа chown, chmod, stat и им подобные требовали от администратора ресурсов, чтобы он сначала анализировал имя пути, а затем уже выполнял нужные действия. (Именно так, кстати, все реализовано в QNX4.) Типичные проблемы этого подхода:

• Каждой функции приходится вызывать процедуру поиска.

• Для функций, у которых есть также версия, ориентированная на файловый дескриптор, драйвер должен обеспечить две отдельные точки входа: одну для версии с именем пути, и еще одну — версии с дескриптором файла.

В QNX/Neutrino же происходит следующее. Клиент создает составное сообщение — реально это одно сообщение, но оно включает в себя несколько сообщений администратору ресурсов. Без составных сообщений мы могли бы смоделировать функцию chown чем-то таким:

int chown(const char *path, uid_t owner, gid_t group) {

 int fd, sts;

 if ((fd = open(path, O_RDWR)) == -1) {

return (-1);

 }

 sts = fchown(fd, owner, group);

 close(fd);

 return (sts);

}

где функция fchown — это версия функции chown, ориентированная на файловые дескрипторы. Проблема здесь в том, что мы в этом случае используем три вызова функций (а значит, и три отдельных транзакции передачи сообщений) и привносим дополнительные накладные расходы применением функций open

и close на стороне клиента.

При использовании составных сообщений в QNX/Neutrino непосредственно клиентским вызовом chown создается одиночное сообщение, выглядящее примерно так:

Составное сообщение.

Сообщение состоит из двух частей. Первая часть посвящена установлению соединения (подобно сообщению, которое сгенерировала бы функция open), вторая — вводу/выводу (эквивалент сообщения, генерируемого функцией fchown). Никакого эквивалента функции close здесь нет, поскольку мы выбрали сообщение типа _IO_CONNECT_COMBINE_CLOSE, которое гласит: «Открой указанное имя пути, используй полученный дескриптор файла для обработки остальной части сообщения, а когда закончишь дела или столкнешься с ошибкой, закрой дескриптор».

Написанный вами администратор ресурса даже не заметит, вызвал ли клиент функцию chown или сначала сделал open, а потом вызвал fchown и далее close. Все это скрыто базовым уровнем библиотеки.

Составные сообщения

Как выясняется, концепция составных сообщений полезна не только для экономии ресурсов вследствие уменьшения числа сообщений (как в случае с chown, см. выше). Она также критически важна для обеспечения атомарности операций.

Предположим, что в клиентском процессе есть два или более потоков, работающих с одним дескриптором файла. Один из потоков в клиенте вызывает функцию lseek, за которой следует read. Все так, как мы и предполагаем. А вот если другой клиента попробует выполнить ту же самую последовательность операций с тем же самым дескриптором файла, вот тут у нас начнутся проблемы. Поскольку функции lseek и read друг о друге ничего не знают, то возможно, например, что первый поток выполнит lseek, а затем будет вытеснен вторым потоком. Второй поток выполнит свои lseek и read, после чего освободит процессор. Проблема здесь состоит в том, что поскольку эти два потока разделяют один и тот же дескриптор файла, у первого потока теперь получается неправильное смещение lseek, поскольку оно было изменено функциями lseek и read второго потока! Эта проблема проявляется также с дескрипторами файлов, которые дублируются (dup) между процессами, не говоря уже о сети.

Очевидным решением здесь является заключение lseek и read в пределы действия мутекса — когда первый поток захватит мутекс, мы будем знать, что он имеет эксклюзивный доступ к дескриптору. Второй поток должен будет ждать освобождения мутекса, прежде чем он сможет творить свое безобразие с позиционированием дескриптора.

К сожалению, если кто-то вдруг забудет захватить мутекс перед каждой и любой операцией с дескриптором файла, всегда остается возможность того, что такой «незащищенный» доступ может привести поток к чтению или записи данных не туда, куда надо.

Поделиться:
Популярные книги

Дарующая счастье

Рем Терин
Любовные романы:
любовно-фантастические романы
6.96
рейтинг книги
Дарующая счастье

Рота Его Величества

Дроздов Анатолий Федорович
Новые герои
Фантастика:
боевая фантастика
8.55
рейтинг книги
Рота Его Величества

Царь поневоле. Том 1

Распопов Дмитрий Викторович
4. Фараон
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Царь поневоле. Том 1

Гром над Империей. Часть 4

Машуков Тимур
8. Гром над миром
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Гром над Империей. Часть 4

Толян и его команда

Иванов Дмитрий
6. Девяностые
Фантастика:
попаданцы
альтернативная история
7.17
рейтинг книги
Толян и его команда

Адепт: Обучение. Каникулы [СИ]

Бубела Олег Николаевич
6. Совсем не герой
Фантастика:
фэнтези
попаданцы
9.15
рейтинг книги
Адепт: Обучение. Каникулы [СИ]

Кротовский, не начинайте

Парсиев Дмитрий
2. РОС: Изнанка Империи
Фантастика:
городское фэнтези
попаданцы
альтернативная история
5.00
рейтинг книги
Кротовский, не начинайте

Невеста клана

Шах Ольга
Фантастика:
попаданцы
фэнтези
5.00
рейтинг книги
Невеста клана

Седьмая жена короля

Шёпот Светлана
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Седьмая жена короля

Черный дембель. Часть 1

Федин Андрей Анатольевич
1. Черный дембель
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Черный дембель. Часть 1

Ваше Сиятельство

Моури Эрли
1. Ваше Сиятельство
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Ваше Сиятельство

Дороги Пламенных

Дмитриева Ольга Олеговна
4. Пламенная
Фантастика:
боевая фантастика
5.00
рейтинг книги
Дороги Пламенных

Наследник павшего дома. Том II

Вайс Александр
2. Расколотый мир [Вайс]
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Наследник павшего дома. Том II

Измена. Свадьба дракона

Белова Екатерина
Любовные романы:
любовно-фантастические романы
эро литература
5.00
рейтинг книги
Измена. Свадьба дракона