================================================================= 5.27 Драйверы платформенных устройств в пространстве пользователя ================================================================= Обзор ----- В Linux-драйверах существует два основных подхода к взаимодействию с оборудованием: - **через пространство ядра** (kernel space) - **через пространство пользователя** (user space) В этом разделе рассматривается практический способ реализации **драйвера для RGB-светодиодов** через `platform_device`, при этом управление осуществляется **из пространства пользователя** через `sysfs` или shell-скрипт. Подход не требует патчей ядра, поддерживает перезагрузку модуля (`rmmod/insmod`) и легко расширяется. Сценарий -------- На практике на Raspberry Pi подключены три светодиода к GPIO, и через простой платформенный драйвер мы: - выделяем пины для каждого цвета (можно через параметры модуля); - регистрируем устройства LED-класса (``led_classdev``); - получаем доступ к ним из `/sys/class/leds/...`. Это создаёт мост между пространством ядра и пользователя, при этом вся логика управления находится **в пользовательских скриптах** (`bash`, `sh`, `Python`, `C`). Преимущества и недостатки ------------------------- Пользовательское пространство (User Space) ------------------------------------------ **Преимущества:** - Удобная отладка — доступны обычные инструменты (`gdb`, `strace`, `printf`) - Можно использовать любые языки (например, Python) - Не требует пересборки ядра - Быстрый доступ к устройству (без системных вызовов на каждом шаге) - Интерфейс API в Linux стабилен **Недостатки:** - Нельзя обрабатывать прерывания - Нет прямого доступа к регистрам и ядровым фреймворкам - Без ядровой части пользовательская часть не может "поднять" устройство Пространство ядра (Kernel Space) -------------------------------- **Преимущества:** - Прямой доступ к железу и прерываниям - Использование инфраструктуры ядра (`platform_device`, `led_classdev`, `pm`, `kobject`) - Возможность одновременного доступа из нескольких процессов - Поддержка шины и автоматической загрузки через `udev` и `modprobe` **Недостатки:** - Сложная отладка (`dmesg`, `printk`, падения ядра) - Системные вызовы при каждом обращении - Частые изменения API между версиями ядра Связь между пространствами --------------------------- Наиболее стабильной и простой связкой между ядром и пользователем является **интерфейс sysfs**: .. code-block:: shell /sys/class/leds/rgb:red/brightness /sys/class/leds/rgb:green/brightness /sys/class/leds/rgb:blue/brightness Из `bash` или любого пользовательского кода можно просто писать: .. code-block:: bash echo 1 > /sys/class/leds/rgb:red/brightness Физически за этим стоит регистрация устройства `led_classdev` в драйвере, который работает как платформенное устройство (см. `platform_driver` API в ядре). Управление из shell ------------------- Можно реализовать управление драйвером из обычного `sh`-скрипта, используя файл, например: .. code-block:: bash echo "red=1" > ./pin echo "green=0" > ./pin А фоновый скрипт `run.sh` будет считывать команды и применять их к `sysfs`. Это создаёт удобную **прослойку между интерфейсом и железом**, где драйвер отвечает за инициализацию, а пользователь — за поведение. Пример архитектуры ------------------ .. code-block:: +---------------------------+ | Пользовательский код | | run.sh / Python / Bash | +---------------------------+ | v +---------------------------+ | sysfs (/sys/class) | +---------------------------+ | v +---------------------------+ | platform_driver | | led_classdev_register() | +---------------------------+ | v +---------------------------+ | GPIO-пины | +---------------------------+ Вывод ------ > Пространство пользователя в связке с ядровыми драйверами — мощный и гибкий подход: логика остаётся на стороне пользователя, а стабильная регистрация устройств и доступ к железу — на стороне ядра. Такой подход особенно актуален в системах на базе **Raspberry Pi**, где разработка ведётся быстро и гибко, без пересборки ядра и перезаписи `dtb`. --- Если нужно — можно дополнить примерами `.ko` модуля, `bash`-интерфейса, `udev`-автозапуска или `/dev/pin` интерфейса через `miscdevice`.