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);
}
}
При том, что функция
Теперь о наиболее важной особенности. Обратите внимание, как мы использовали для выполнения всей нашей работы функции POSIX-уровня по умолчанию! Функция
Все, что мы должны сделать — это решить,
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);
}
}
В функции
Приведенный ниже код ничего не знает о наших специальных устройствах, да ему, собственно, и дела до них нет — он просто принимает решение на основе стандартных общеизвестных данных.
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));
Бьерн Страуструп , Бьёрн Страуструп , Валерий Федорович Альмухаметов , Ирина Сергеевна Козлова
Программирование, программы, базы данных / Базы данных / Программирование / Учебная и научная литература / Образование и наука / Книги по IT