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