30. Как работает UIO
Каждое UIO-устройство в Linux доступно через специальный файловый интерфейс и набор атрибутов в sysfs.
Основной файл для доступа — это /dev/uioX, где X — номер устройства (например, /dev/uio0, /dev/uio1 и т.д.). Кроме того, ядро создаёт папки с атрибутами в каталоге /sys/class/uio/.
Пример структуры для первого устройства:
/sys/class/uio/uio0 — корень атрибутов этого устройства.
/sys/class/uio/uio0/name — содержит строковое имя устройства (устанавливается в struct uio_info).
/sys/class/uio/uio0/maps/ — содержит информацию о доступных областях памяти.
Каждое устройство может предоставить одну или несколько областей памяти (mmap). Для каждой такой области создаётся отдельная директория, например:
/sys/class/uio/uio0/maps/map0/
/sys/class/uio/uio0/maps/map1/ и т.д.
Внутри каждой mapX/ директории находятся файлы:
name — имя области (можно оставить пустым)
addr — физический адрес области, доступной для mmap
size — размер области в байтах
offset — смещение от начала mmap, которое нужно прибавить для получения реального указателя на память устройства. Это важно, если память не выровнена по границе страницы.
Прерывания обрабатываются просто: Вызывается read() из /dev/uioX, и он блокируется, пока не произойдёт прерывание. Можно также использовать select() или poll().
Чтение возвращает целое число, показывающее количество прерываний с момента загрузки драйвера. Это помогает определить, были ли пропущены прерывания (например, если счётчик увеличился больше чем на 1).
Доступ к памяти осуществляется через вызов mmap(), который мапит память устройства в адресное пространство пользовательского приложения.
Итог: UIO предоставляет очень простой способ получить доступ к памяти устройства и к его прерываниям — напрямую из пространства пользователя, через стандартные системные вызовы.