};
Коротко о ее полях:
d_ino | «Индексный дескриптор» («inode») — уникальный для точки монтирования порядковый номер, который не может быть нулевым (нуль указывал бы на то, что элемент, соответствующий данному индексному дескриптору, является свободным/пустым). |
d_offset | Смещение в каталоге, о котором мы только что говорили. В нашем примере это будут обычные числа типа «0», «1», «2», и т.д. |
d_reclen | Размер структуры struct dirent целиком, включая любые добавляемые в нее расширения. Заполнители для выравнивания при вычислении размера учитываются. |
d_namelen | Число символов в поле d_name, не включая признак конца строки NULL. |
d_name | Имя элемента каталога, которое должно завершаться признаком конца строки — NULL. |
При возврате структур типа struct dirent
код возврата, который передается клиенту, представляет собой число возвращенных байт.
Давайте для примера создадим администратора каталогового ресурса /dev/atoz
. Этот администратор зарегистрирует «файлы» с именами от /dev/atoz/a
до /dev/atoz/z
, чтобы команда cat, примененная к любому из них, возвращала соответствующие их именам заглавные буквы. Чтобы понять, как это должно работать, вот пример командно-строковой сессии:
# cd /dev
# ls
atoz null ptyp2 socket ttyp0 ttyp3
enet0 ptyp0 ptyp3 text ttyp1 zero
mem ptyp1 shmem tty ttyp2
# ls -ld atoz
dr-xr-xr-x 1 root 0 26 Sep 05 07:59 atoz
# cd atoz
# ls
a e i m q u y
b f j n r v z
c g k o s w
d h l p t x
# ls -l e
-r--r--r-x 1 root 0 1 Sep 05 07:59 e
# cat m
M# cat q
Q#
Приведенный пример показывает, что в каталоге /dev
есть каталог atoz
, и что к нему можно применить команду ls
и выполнить в него cd
. Данный каталог /dev/atoz
имеет размер «26» — мы так задали в нашей программе. Сменив текущий каталог на atoz
и выполнив еще одну ls
, получаем его содержимое — файлы с именами от а
до z
. Выполнив ls
для отдельного файла — в данном случае для файла e
— мы видим, что файл доступен по чтению всем (часть «-r--r--r--
») и имеет размер, равный 1 байту. Наконец, выполнение нескольких cat
показывает, что файлы действительно имеют заявленное содержимое. (Отметим, что поскольку файлы содержат только один байт и не содержат символа новой строки, после вывода символа строка не переводится, и приглашение командного интерпретатора оказывается на той же самой строке, что и вывод cat
.)
Теперь, когда мы знаем нужные характеристики, давайте посмотрим на код. Он разбит на следующие функции:
main() и декларации
Основная функция; здесь мы все инициализируем и запускаем наш администратор ресурса.
my_open()
Обработчик сообщения _IO_CONNECT.
my_read()
Обработчик сообщения _IO_READ.
my_read_dir() и my_read_file()
Выполняют фактическую работу функции my_read().
dirent_size() и dirent_fill()
Сервисные функции для работы со структурой struct diren
t.
Заметьте, что при том, что разбит на короткие секции, перемежаемые текстовыми пояснениями, архив с полным исходным текстом в виде единого файла можно взять на веб-сайте компании PARSE Software Devices (http://www.parse.com/
), он называется atoz.c.
Первый приведенный раздел программы представляет собой функцию main() и ряд деклараций. Для удобства объявлен макрос ALIGN(), который используется функциями dirent_size() и dirent_fill() для выравнивания.
Массив atoz_attrs содержит атрибутные записи, используемые в этом примере для «файлов». Мы объявляем массив из NUM_ENTS элементов, потому что у нас есть NUM_ENTS (то есть 26) файлов — от «а
» до «z
». Атрибутная запись, применяемая непосредственно для каталога (то есть для /dev/atoz
, объявлена в теле функции main() и называется просто attr. Обратите внимание на различное содержимое у этих двух типов атрибутных записей:
Файловая атрибутная запись:
Маркируется как обычный файл (константа S_IFREG) с режимом доступа 0444 (это означает, что доступ по чтению имеет каждый, но доступа по записи нет ни у кого). Размер равен «1» — файл содержит только один байт, а именно прописную букву, соответствующую своему имени. Индексные дескрипторы (inodes) этих файлов пронумерованы от «1» до «26» включительно (было бы удобнее взять числа от «0» до «25», но цифра «0» зарезервирована).
Каталоговая атрибутная запись:
Маркируется как файл типа «каталог» (константа S_IFDIR) с режимом доступа 0555 (это означает, что доступ по чтению и поиску имеет каждый, но доступа по записи нет ни у кого). Размер определен как «26» — это просто число, взятое по количеству элементов в каталоге. Индексный дескриптор выбран равным «27» — это число заведомо не используется больше ни в одной атрибутной записи.
Обратите внимание, что мы переопределили только поле open структуры connect_func и поле read структуры io_func. Для всех остальных полей сохранены POSIX-значения по умолчанию.
Наконец, обратите внимание, как мы создали имя /dev/atoz
, используя resmgr_attach(). Наиболее важным здесь является то, что мы применили флаг _RESMGR_FLAG_DIR, который сообщает администратору процессов, что он может разрешать запросы на эту точку монтирования и ниже.
/*
* atoz.с
*
* /dev/atoz с использованием библиотеки администратора ресурсов
*/
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <errno.h>
#include <dirent.h>