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

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

Жанры

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

Кёртен Роб

Шрифт:

 // ...и для имен от «a» до «z»

 for (i = 0; i < NUM_ENTS; i++) {

iofunc_attr_init(&atoz_attrs[i], S_IFREG | 0444, 0, 0);

atoz_attrs[i].inode = i + 1;

atoz_attrs[i].nbytes = 1;

 }

 // Добавить наши функции; нам интересны только io_open

 // и io_read

 connect_func.open = my_open;

 io_func.read = my_read;

 // Зарегистрировать префикс

 if (resmgr_attach(dpp, &resmgr_attr, "/dev/atoz",

_FTYPE_ANY, _RESMGR_FLAG_DIR, &connect_func,

&io_func, &attr) == -1) {

perror("Ошибка resmgr_attach\n");

exit(EXIT_FAILURE);

 }

 //
Выделить контекст

 ctp = resmgr_context_alloc(dpp);

 // Ждать сообщений в вечном цикле

 while (1) {

if ((ctp = resmgr_block(ctp)) == NULL) {

perror("Ошибка resmgr_block\n");

exit(EXIT_FAILURE);

}

resmgr_handler(ctp);

 }

}

my_open

При том, что функция my_open очень невелика, в ней есть ряд критических мест. Обратите внимание, как мы принимаем решение о том, был ли ресурс открыт как «файл» или как «каталог», на основе только длины имени пути. Мы можем себе это позволить, потому что знаем, что других каталогов, кроме основного, в этом администраторе ресурсов нет. Если вы захотите расположить ниже вашей точки монтирования дополнительные каталоги, вам придется применить более сложный механизм анализа поля path структуры msg. В нашем простом примере, если в имени пути ничего нет, то мы знаем, что это каталог. Также обратите внимание на чрезвычайно упрощенную проверку корректности имени пути: мы просто проверяем, что у нас действительно только один символ, и что он лежит в диапазоне от «a» до «z» включительно. Опять же, в случае более сложного администратора ресурсов вам пришлось бы выполнять синтаксический анализа имени, следующего за зарегистрированной точкой монтирования.

Теперь о наиболее важной особенности. Обратите внимание, как мы использовали для выполнения всей нашей работы функции POSIX-уровня по умолчанию! Функция iofunc_open_default обычно размещается в таблице функций установления соединения в той же самой ячейке, которую сейчас занимает наша функция my_open. Это означает, что они принимают одинаковый набор аргументов!

Все, что мы должны сделать — это решить, какую атрибутную запись мы хотим связать с OCB, создаваемым функцией по умолчанию: либо каталоговую (в этом случае мы передаем attr), либо одну из 26 имеющихся у нас файловых (тогда мы передаем соответствующий элемент atoz_attrs). Это ключевой момент, поскольку обработчик, который вы помещаете в слот open в таблице функций установления соединения, действует как «швейцар» по отношению ко всем последующим запросам к вашему администратору ресурса.

static int my_open(resmgr_context_t *ctp, io_open_t *msg,

 iofunc_attr_t *attr, void *extra) {

 if (msg->connect.path[0] == 0) {

// Каталог (/dev/atoz)

return (iofunc_open_default(ctp, msg, attr, extra));

 } else if (msg->connect.path[1] == 0 &&

(msg->connect.path[0] >= 'a' &&

msg->connect.path[0] <= 'z')) { //
Файл (/dev/atoz/[a-z])

return

(iofunc_open_default(ctp, msg, atoz_attrs +

msg->connect.path[0] - 'a', extra));

 } else {

return (ENOENT);

 }

}

my_read

В функции my_read, чтобы решить, какие операции надо выполнить, мы анализируем поле mode атрибутной записи. Если макрос S_ISDIR говорит, что это каталог, мы вызываем функцию my_read_dir; если макрос S_ISREG говорит, что это файл, мы вызываем функцию my_read_file. (Отметим, что если мы не можем разобрать, что это такое, мы возвращаем клиенту EBADF, указывая ему этим, что что-то здесь не так.)

Приведенный ниже код ничего не знает о наших специальных устройствах, да ему, собственно, и дела до них нет — он просто принимает решение на основе стандартных общеизвестных данных.

static int my_read(resmgr_context_t *ctp, io_read_t *msg,

 iofunc_ocb_t *ocb) {

 int sts;

 // Использовать вспомогательную функцию для проверки

 // корректности

 if ((sts =

iofunc_read_verify(ctp, msg, ocb, NULL)) != EOK) {

return (sts);

 }

 // Решить, надо ли читать «файл» или «каталог»

 if (S_ISDIR(ocb->attr->mode)) {

return (my_read_dir(ctp, msg, ocb));

 } else if (S_ISREG(ocb->attr->mode)) {

return (my_read_file(ctp, msg, ocb));

 } else {

return (EBADF);

 }

}

my_read_dir

Вот тут-то все веселье и начинается. С точки зрения высокого уровня, мы выделяем буфер (он называется reply_msg), в котором собираемся разместить результат операции. Затем мы используем dp, чтобы «прогуляться» по буферу, заполняя его по ходу дела элементами

struct dirent
. Вспомогательная подпрограмма dirent_size применяется, чтобы определить, есть ли у нас место в буфере для еще одного элемента. Вспомогательная подпрограмма dirent_fill кладет элемент в буфер. (Отметим, что эти подпрограммы не входят в библиотеку администратора ресурсов; мы обсудим их ниже.)

На первый взгляд этот код может показаться неэффективным; мы используем функцию sprintf для создания двухбайтового имени файла (символ имени файла и признак конца строки NULL) в буфере длиной _POSIX_PATH_MAX (то есть 256) байт. Это делается для того, чтобы сделать код по возможности универсальным.

Наконец, обратите внимание, что мы используем поле offset в OCB для указания, для какого конкретного файла мы в данный момент генерируем структуру

struct dirent
. Это означает, что мы также должны корректировать поле offset всякий раз, когда возвращаем данные.

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

Вперед в прошлое 2

Ратманов Денис
2. Вперед в прошлое
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Вперед в прошлое 2

Главная роль 4

Смолин Павел
4. Главная роль
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Главная роль 4

Крестоносец

Ланцов Михаил Алексеевич
7. Помещик
Фантастика:
героическая фантастика
попаданцы
альтернативная история
5.00
рейтинг книги
Крестоносец

Отмороженный 3.0

Гарцевич Евгений Александрович
3. Отмороженный
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Отмороженный 3.0

Я еще не князь. Книга XIV

Дрейк Сириус
14. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я еще не князь. Книга XIV

Идеальный мир для Лекаря 26

Сапфир Олег
26. Лекарь
Фантастика:
аниме
фэнтези
5.00
рейтинг книги
Идеальный мир для Лекаря 26

Кодекс Крови. Книга IV

Борзых М.
4. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга IV

Снегурка для опера Морозова

Бигси Анна
4. Опасная работа
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Снегурка для опера Морозова

Шериф

Астахов Евгений Евгеньевич
2. Сопряжение
Фантастика:
боевая фантастика
постапокалипсис
рпг
6.25
рейтинг книги
Шериф

Измена. Он все еще любит!

Скай Рин
Любовные романы:
современные любовные романы
6.00
рейтинг книги
Измена. Он все еще любит!

Неудержимый. Книга III

Боярский Андрей
3. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Неудержимый. Книга III

Чужая семья генерала драконов

Лунёва Мария
6. Генералы драконов
Фантастика:
фэнтези
5.00
рейтинг книги
Чужая семья генерала драконов

Адвокат вольного города

Парсиев Дмитрий
1. Адвокат
Фантастика:
городское фэнтези
альтернативная история
аниме
5.00
рейтинг книги
Адвокат вольного города

Изгой Проклятого Клана. Том 2

Пламенев Владимир
2. Изгой
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Изгой Проклятого Клана. Том 2