30. Как работает UIO

Каждое UIO-устройство в Linux доступно через специальный файловый интерфейс и набор атрибутов в sysfs.

Основной файл для доступа — это /dev/uioX, где X — номер устройства (например, /dev/uio0, /dev/uio1 и т.д.). Кроме того, ядро создаёт папки с атрибутами в каталоге /sys/class/uio/.

Пример структуры для первого устройства:

  1. /sys/class/uio/uio0 — корень атрибутов этого устройства.

  2. /sys/class/uio/uio0/name — содержит строковое имя устройства (устанавливается в struct uio_info).

  3. /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 предоставляет очень простой способ получить доступ к памяти устройства и к его прерываниям — напрямую из пространства пользователя, через стандартные системные вызовы.