28. 5.27 Драйверы платформенных устройств в пространстве пользователя

28.1. Обзор

В Linux-драйверах существует два основных подхода к взаимодействию с оборудованием:

  • через пространство ядра (kernel space)

  • через пространство пользователя (user space)

В этом разделе рассматривается практический способ реализации драйвера для RGB-светодиодов через platform_device, при этом управление осуществляется из пространства пользователя через sysfs или shell-скрипт.

Подход не требует патчей ядра, поддерживает перезагрузку модуля (rmmod/insmod) и легко расширяется.

28.2. Сценарий

На практике на Raspberry Pi подключены три светодиода к GPIO, и через простой платформенный драйвер мы:

  • выделяем пины для каждого цвета (можно через параметры модуля);

  • регистрируем устройства LED-класса (led_classdev);

  • получаем доступ к ним из /sys/class/leds/….

Это создаёт мост между пространством ядра и пользователя, при этом вся логика управления находится в пользовательских скриптах (bash, sh, Python, C).

28.3. Преимущества и недостатки

28.4. Пользовательское пространство (User Space)

Преимущества:

  • Удобная отладка — доступны обычные инструменты (gdb, strace, printf)

  • Можно использовать любые языки (например, Python)

  • Не требует пересборки ядра

  • Быстрый доступ к устройству (без системных вызовов на каждом шаге)

  • Интерфейс API в Linux стабилен

Недостатки:

  • Нельзя обрабатывать прерывания

  • Нет прямого доступа к регистрам и ядровым фреймворкам

  • Без ядровой части пользовательская часть не может «поднять» устройство

28.5. Пространство ядра (Kernel Space)

Преимущества:

  • Прямой доступ к железу и прерываниям

  • Использование инфраструктуры ядра (platform_device, led_classdev, pm, kobject)

  • Возможность одновременного доступа из нескольких процессов

  • Поддержка шины и автоматической загрузки через udev и modprobe

Недостатки:

  • Сложная отладка (dmesg, printk, падения ядра)

  • Системные вызовы при каждом обращении

  • Частые изменения API между версиями ядра

28.6. Связь между пространствами

Наиболее стабильной и простой связкой между ядром и пользователем является интерфейс sysfs:

/sys/class/leds/rgb:red/brightness
/sys/class/leds/rgb:green/brightness
/sys/class/leds/rgb:blue/brightness

Из bash или любого пользовательского кода можно просто писать:

echo 1 > /sys/class/leds/rgb:red/brightness

Физически за этим стоит регистрация устройства led_classdev в драйвере, который работает как платформенное устройство (см. platform_driver API в ядре).

28.7. Управление из shell

Можно реализовать управление драйвером из обычного sh-скрипта, используя файл, например:

echo "red=1" > ./pin
echo "green=0" > ./pin

А фоновый скрипт run.sh будет считывать команды и применять их к sysfs.

Это создаёт удобную прослойку между интерфейсом и железом, где драйвер отвечает за инициализацию, а пользователь — за поведение.

28.8. Пример архитектуры

+---------------------------+
|     Пользовательский код  |
|  run.sh / Python / Bash   |
+---------------------------+
          |
          v
+---------------------------+
|       sysfs (/sys/class) |
+---------------------------+
          |
          v
+---------------------------+
|      platform_driver      |
| led_classdev_register()   |
+---------------------------+
          |
          v
+---------------------------+
|         GPIO-пины         |
+---------------------------+

28.9. Вывод

> Пространство пользователя в связке с ядровыми драйверами — мощный и гибкий подход: логика остаётся на стороне пользователя, а стабильная регистрация устройств и доступ к железу — на стороне ядра.

Такой подход особенно актуален в системах на базе Raspberry Pi, где разработка ведётся быстро и гибко, без пересборки ядра и перезаписи dtb.

—

Если нужно — можно дополнить примерами .ko модуля, bash-интерфейса, udev-автозапуска или /dev/pin интерфейса через miscdevice.