Вход/Регистрация
Введение в 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
  • Читать дальше
  • 1
  • ...
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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