Встраиваемые системы

Linux Kernel Drivers

Каждый раз когда камера смартфона делает фото, GPU рендерит кадр или WiFi чип принимает пакет - это работа kernel driver. Написать неправильный driver - kernel panic. Написать с утечкой памяти - через неделю система падает. В ядре нет второго шанса.

  • **Tesla FSD** компьютер использует кастомные NVIDIA kernel drivers для доступа к нейронным процессорам с latency < 5 мс - platform drivers с DMA для видеопотоков с 8 камер
  • **Android Camera HAL** построен поверх V4L2 (Video for Linux 2) - стандартизированного kernel subsystem на основе char/platform drivers. Каждый производитель смартфона пишет свои media drivers
  • **Industrial PLC** (Siemens, Rockwell) используют EtherCAT real-time Ethernet как kernel module с DMA для детерминированной задержки < 100 мкс в производственных линиях

Character Driver: /dev/mydevice как файл

В Linux всё - файл. Сетевая карта, датчик температуры, акселерометр на I2C шине. Это не метафора - это архитектурное решение, принятое в 1969 году. Character driver - механизм, который превращает любое устройство в файл `/dev/something`. Userspace открывает файл, читает, пишет. Ядро маршрутизирует вызовы в ваш код.

Character device - это устройство без seek-операций, данные читаются/пишутся последовательно. Противоположность - block device (диск). Для большинства IoT-сенсоров char driver - правильный выбор. GPIO, ADC, кастомные протоколы по SPI - всё это char drivers.

copy_to_user/copy_from_user - не просто memcpy. Они проверяют что userspace указатель валиден и не указывает в kernel space. Прямой доступ к userspace памяти из ядра без этих функций - уязвимость privilege escalation. Аналог - SQL parameterized queries vs string concatenation.

Почему нельзя использовать обычный memcpy для копирования данных между kernel space и user space?

Platform Driver: интеграция с Device Tree

Character driver - это низкоуровневый механизм. Platform driver - это слой поверх него, который интегрируется с Device Tree и системой управления питанием. Когда ядро читает DTB и находит совместимое устройство, оно автоматически вызывает `probe()` соответствующего драйвера. Нет ручной инициализации, нет магических номеров в коде.

Система compatible strings - как dependency injection в Spring. DTB говорит `compatible = "mycompany,mysensor"`. Ядро ищет драйвер с таким же `compatible` в OF_MATCH_TABLE. Находит - вызывает probe. Не находит - устройство остаётся неинициализированным. Никаких hardcoded адресов в коде.

devm_* функции (devm_kzalloc, devm_ioremap) - managed resources. При remove или ошибке в probe они автоматически освобождаются. Аналог RAII в C++ или defer в Go. Без devm_ - ручное управление памятью в ядре, гарантированные утечки при ошибках.

Как platform driver узнает, что конкретное устройство из Device Tree относится к нему?

Device Tree Binding: документация как контракт

Device Tree binding - это формальная спецификация того, какие свойства поддерживает конкретный драйвер. С 2019 года Linux требует YAML-схемы для всех новых binding. dt-validate проверяет DTB против схем - как TypeScript проверяет типы. Без валидации в ядро не принимают патч.

Зачем это нужно? ML-параллель: binding-схема для драйвера - как ONNX-схема для модели. Производитель оборудования публикует binding, firmware-инженер пишет DTS по схеме, dt-validate ловит ошибки до компиляции. Без этой стандартизации каждый vendor изобретал свои property-имена - хаос, который и уничтожили этой системой.

Для чего нужны YAML binding schemas в современном Linux kernel?

DMA: zero-copy для high-throughput устройств

Камера 4K при 30 fps генерирует 3840 x 2160 x 3 байта x 30 = 750 МБ/с. Если каждый кадр копировать через CPU: memcpy на 750 МБ/с займёт весь ресурс ARM Cortex-A53. DMA (Direct Memory Access) позволяет периферии писать напрямую в RAM, минуя CPU. CPU только настраивает транзакцию и получает interrupt при завершении.

DMA coherency - главная сложность. CPU видит данные через cache, DMA пишет в физическую RAM. Без cache coherency CPU читает устаревшие данные из L1/L2. Решения: dma_alloc_coherent (некэшируемая память, медленнее), dma_sync_* (явная инвалидация кэша). Аналог - cache invalidation в distributed systems, только на уровне кремния.

DMA всегда быстрее CPU-copy, поэтому его нужно использовать везде

DMA имеет overhead на настройку транзакции. Для малых объёмов (< 1 KB) CPU-copy быстрее. DMA выгоден при постоянном потоке данных > нескольких КБ

Настройка DMA descriptor, синхронизация с контроллером, interrupt handling занимают сотни наносекунд. Для одного short transfer этот overhead превышает выигрыш от разгрузки CPU

Почему для DMA нужна специальная функция dma_alloc_coherent, а не обычный kmalloc?

Связанные темы

Kernel drivers пересекаются с фундаментальными концепциями CS:

  • System Calls — Char drivers регистрируют file_operations, которые вызываются через syscall interface
  • I/O в операционных системах — Kernel drivers - конкретная реализация I/O subsystem теории ОС
  • Embedded Linux (Yocto/Buildroot) — Device Tree binding схемы из этого урока используются в Yocto recipes

Ключевые идеи

  • **Character driver** - `/dev/device` как файл. file_operations struct: open/read/write/ioctl. copy_to_user/copy_from_user - обязательно, не memcpy.
  • **Platform driver** - интеграция с Device Tree через compatible strings и OF_MATCH_TABLE. probe() автовызывается ядром. devm_* managed resources.
  • **DT Binding YAML схемы** - обязательны с Linux 5.4+ для mainline. dt-validate проверяет DTS файлы. Формальный контракт между hardware и software.
  • **DMA** - zero-copy transfers для high-throughput. dma_alloc_coherent для cache coherency. Cyclic DMA для непрерывных потоков (ADC, camera, audio). Overhead на setup - не использовать для < 1 KB.

Вопросы для размышления

  • Character driver vs platform driver: когда использовать каждый? Какой критерий выбора?
  • Cache coherency в DMA - это та же проблема, что consistency в distributed systems. Какие аналогии и различия?
  • YAML binding schemas делают Device Tree 'типизированным'. Какие плюсы и минусы по сравнению с неформальной документацией?

Связанные уроки

  • emb-15 — Device Tree из uroka 15 необходим для platform drivers
  • os-15-syscalls — Syscall interface - точка входа из userspace в kernel space
  • os-10-io — Kernel drivers реализуют I/O абстракции из теории ОС
  • alg-21-dp — DMA scatter-gather похож на DP: разбиение большой задачи на оптимальные части
  • os-01-intro
Linux Kernel Drivers

0

1

Войти