Шрифт:
Администратор | Флаг | Очередность |
---|---|---|
1 | _RESMGR_BEFORE | 1 |
2 | _RESMGR_AFTER | 1, 2 |
3 | 0 | 1, 3 ,2 |
4 | _RESMGR_BEFORE | 1, 4, 3, 2 |
5 | _RESMGR_AFTER | 1, 4, 3, 5, 2 |
6 | 0 | 1, 4, 6, 3, 5, 2 |
Из таблицы видно, что первый администратор ресурса, явно определивший флаг, далее не сдвигается со своей позиции.(См. таблицу: администратор ресурсов № 1 был первым определившим флаг «BEFORE»; кто бы теперь ни зарегистрировался, он так и останется первым в списке. Аналогично, администратор ресурсов № 2 был первым определившим флаг «AFTER» — и снова, независимо от того, кто еще будет регистрироваться после него, он всегда остается в списке последним.) Если не определен никакой флаг, это действует как флаг «между». Когда стартует администратор ресурсов № 3 (указав нулевой флаг), он помещается в середину очереди. Как и в случае с флагами «BEFORE» и «AFTER», здесь имеет место упорядочивание, в результате чего все вновь регистрирующиеся «средние» администраторы ресурсов располагаются перед уже зарегистрированными «средними».
Однако, в действительности, только в очень редких случаях вам придется регистрировать более одного, и в еще меньшем числе случаев — более двух администраторов ресурсов при той же самой точке монтирования. Полезный совет: обеспечьте возможность установки флагов непосредственно в командной строке администратора ресурса, чтобы конечный пользователь вашего администратора ресурса мог сам задать, например, флаг «BEFORE» опцией
Имейте в виду, что данное обсуждение применимо только для администраторов ресурсов, регистрируемых при одной и той же точке монтирования. Монтирование «
И наконец, функция resmgr_attach в случае успешного завершения возвращает дескриптор (handle) в виде небольшого целого числа (или -1 при неудаче). Этот дескриптор можно затем применить для того, чтобы убрать данное имя пути из внутренней таблицы имен путей администратора процессов.
Проектируя свой самый первый администратор ресурсов вы, скорее всего, захотите действовать постепенно. Было бы очень досадно написать несколько тысяч строк кода только для того, чтобы понять, что в самом начале была допущена фундаментальная ошибка, и теперь придется либо наспех затыкать дырки (э-э, я хотел сказать — вносить коррективы), либо выкинуть все это и начать заново.
Чтобы все работало как надо, рекомендуемым подходом здесь является использование функции-инициализатора iofunc_func_init из уровня POSIX, чтобы заполнить таблицы функций установления соединения и функций ввода/вывода заданными по умолчанию функциями POSIX-уровня. Это значит; что вы можете фактически написать каркас вашего администратора ресурсов, как мы уже делали выше, с помощью всего нескольких вызовов.
Какую функцию запрограммировать первой — это будет зависеть от того, какой администратор ресурсов вы пишете. Если это администратор файловой системы, отвечающий за точку монтирования и все, что под ней, то вам, скорее всего, лучше всего начать с функции io_open. С другой стороны, если вы пишете администратор ресурса с дискретной точкой монтирования, который выполняет «традиционные» операции ввода/вывода (то есть вы будете общаться с ним преимущественно вызовами типа read и write), то лучшей стартовой позицией для вас были бы функции io_read и/или io_write. Если же вы пишете администратор ресурса с дискретной точкой монтирования, но вместо «традиционных» операций ввода/вывода основу его функциональности составляют вызовы типа devctl или ioctl, то правильнее было бы начать с io_devctl.
Независимо от того, с чего вы начинаете, вам нужно будет удостовериться в том, что ваши функции вызываются так, как вы предполагаете. В данном ключе функции-обработчики POSIX- уровня по умолчанию обладают очень полезным свойством — их можно помещать непосредственно в таблицы функций установления соединения и таблицы функций ввода/вывода.
Это означает, что если вы захотите что-то дополнительно проконтролировать, просто добавьте дополнительный диагностический вызов printf, чтобы он сказал что-то типа «Я тут!», а затем делайте «то, что надо сделать» — все очень просто.
Вот фрагмент администратора ресурсов, который перехватывает функцию io_open:
Если вы описали функцию io_open корректно, как в этом примере кода, то вы можете вызывать функцию, заданную по умолчанию, из вашей собственной!