Характеристики администраторов ресурсов
Характеристики администраторов ресурсов
Как мы увидели в приведенных выше примерах, ключом к универсальности администраторов ресурсов является возможность использования стандартных функций POSIX — мы ведь не использовали никакие «специальные» функции, когда общались с последовательным портом. А если вам понадобится сделать нечто «особенное», характерное только для применяемого вами устройства? Например, операция настройки скорости обмена по последовательному порту в бодах специфична для администратора последовательного порта, но абсолютно бессмысленна для администратора файловой системы. Аналогично, операция по позиционированию в файле с помощью функции lseek() имеет смысл для файловой системы, но является несодержательной для последовательного порта. В POSIX эта проблема решается просто. Некоторые функции — например, lseek() — при попытке применить их к устройству, которое их не поддерживает, просто возвращают код ошибки. Для реализации функций, специфичных для каждого устройства, в POSIX предусмотрена функция управления устройствами, devctl(). Если устройство не понимает команду, передаваемую ему посредством devctl(), оно просто возвращают код ошибки, аналогично устройствам, которые не понимают функцию lseek().
Поскольку мы уже упомянули функции lseek() и devctl() как общеупотребительные, следует заметить, что администраторы ресурсов обычно поддерживают весь спектр функций, работающих с дескрипторами файлов (или FILE* stream).
Это естественно приводит нас к выводу о том, что администраторы ресурсов будут работать почти исключительно с вызовами дескриптор-ориентированных функций. Поскольку QNX/Neutrino — операционная система, организованная на основе обмена сообщениями, из этого следует, что вызовы POSIX-функций транслируются в сообщения, которые затем пересылаются администраторам ресурсов.
Именно эта трансляция вызовов POSIX в сообщения позволяет нам отвязать клиентуру от администраторов ресурсов. Все, что должен уметь делать администратор ресурса, — это обрабатывать ряд строго определенных сообщений. Все, что должен уметь делать клиент, — это генерировать эти самые строго определенные сообщения, которые администратор ресурса ожидает принимать и обрабатывать.
Поскольку взаимодействие между клиентурой и администраторами ресурсов основано на обмене сообщениями, имеет смысл делать этот «передаточный уровень» как можно «тоньше». Например, когда клиент выполняет функцию open() и получает в ответ дескриптор файла, этот дескриптор фактически является идентификатором соединения! Данный идентификатор соединения (он же дескриптор файла) используется затем функциями клиентской Си-библиотеки (например, функцией read()) при создании и отправке сообщения для администратора ресурсов.