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

на главную

Жанры

Введение в 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 в пределы действия мутекса — когда первый поток захватит мутекс, мы будем знать, что он имеет эксклюзивный доступ к дескриптору. Второй поток должен будет ждать освобождения мутекса, прежде чем он сможет творить свое безобразие с позиционированием дескриптора.

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

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

Газлайтер. Том 8

Володин Григорий
8. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 8

На Ларэде

Кронос Александр
3. Лэрн
Фантастика:
фэнтези
героическая фантастика
стимпанк
5.00
рейтинг книги
На Ларэде

Охота на попаданку. Бракованная жена

Герр Ольга
Любовные романы:
любовно-фантастические романы
5.60
рейтинг книги
Охота на попаданку. Бракованная жена

Кай из рода красных драконов

Бэд Кристиан
1. Красная кость
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Кай из рода красных драконов

Хозяйка Проклятой Пустоши. Книга 2

Белецкая Наталья
2. Хозяйка Проклятой Пустоши
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Хозяйка Проклятой Пустоши. Книга 2

Безумный Макс. Поручик Империи

Ланцов Михаил Алексеевич
1. Безумный Макс
Фантастика:
героическая фантастика
альтернативная история
7.64
рейтинг книги
Безумный Макс. Поручик Империи

Потусторонний. Книга 2

Погуляй Юрий Александрович
2. Господин Артемьев
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Потусторонний. Книга 2

Чапаев и пустота

Пелевин Виктор Олегович
Проза:
современная проза
8.39
рейтинг книги
Чапаев и пустота

Солнечный корт

Сакавич Нора
4. Все ради игры
Фантастика:
зарубежная фантастика
5.00
рейтинг книги
Солнечный корт

Лютая

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

Ведьмак (большой сборник)

Сапковский Анджей
Ведьмак
Фантастика:
фэнтези
9.29
рейтинг книги
Ведьмак (большой сборник)

Наследие Маозари 4

Панежин Евгений
4. Наследие Маозари
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Наследие Маозари 4

Ученик

Губарев Алексей
1. Тай Фун
Фантастика:
фэнтези
5.00
рейтинг книги
Ученик

Начальник милиции. Книга 5

Дамиров Рафаэль
5. Начальник милиции
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Начальник милиции. Книга 5