Встроенные драйверы устройств Linux:понимание их роли
Примечание редактора. Встроенный Linux неизменно входит в число лучших операционных систем, используемых при проектировании встроенных систем. С быстрым ростом интереса к Интернету вещей (IoT) способность встроенного Linux выполнять несколько ролей окажется жизненно важной для поддержки разнообразных потребностей, обнаруживаемых на каждом уровне иерархии приложений IoT. В свою очередь, способность инженеров освоить встраиваемые системы Linux станет критически важной для обеспечения быстрой и надежной разработки более сложных систем. В книге «Освоение программирования на встраиваемых системах Linux - второе издание» автор Крис Симмондс проводит читателя в подробном обзоре широты и глубины этой важной операционной системы, используя подробные примеры для иллюстрации каждого ключевого момента.
В этом отрывке из главы 9 книги автор описывает, как драйверы устройств ядра взаимодействуют с аппаратным обеспечением системы и как разработчики могут писать драйверы устройств и использовать их в своих приложениях. В следующих статьях представлен этот отрывок о драйверах устройств для встроенных Linux:
• Понимание их роли
• Чтение состояния драйвера во время выполнения
• Драйверы устройств в пользовательском пространстве
• Написание драйвера устройства ядра
• Обнаружение конфигурации оборудования
По материалам Освоение программирования на встраиваемых системах Linux - второе издание, Крис Симмондс.
Глава 9. Взаимодействие с драйверами устройств
Драйверы устройств ядра - это механизм, через который базовое оборудование доступно для остальной части системы. Как разработчик встроенных систем, вам необходимо знать, как эти драйверы устройств вписываются в общую архитектуру и как получить к ним доступ из программ пользовательского пространства. В вашей системе, вероятно, будет какое-то новое оборудование, и вам придется разработать способ доступа к ним. Во многих случаях вы обнаружите, что для вас предоставлены драйверы устройств, и вы можете добиться всего, что захотите, без написания кода ядра. Например, вы можете управлять контактами GPIO и светодиодами с помощью файлов в sysfs, и есть библиотеки для доступа к последовательным шинам, включая SPI (последовательный периферийный интерфейс) . и I 2 C (Межинтегральная схема).
Есть много мест, где можно узнать, как написать драйвер устройства, но мало кто расскажет, зачем вам это нужно, и какие у вас есть варианты при этом. Это то, что я хочу здесь осветить. Однако помните, что эта книга не посвящена написанию драйверов устройств ядра и что информация, представленная здесь, предназначена для помощи в навигации по территории, но не обязательно для создания там дома. Есть много хороших книг и статей, которые помогут вам написать драйверы устройств, некоторые из которых перечислены в конце этой главы.
В этой главе мы рассмотрим следующие темы:
-
Роль драйверов устройств
-
Символьные устройства
-
Блокировать устройства
-
Сетевые устройства
-
Информация о драйверах во время выполнения
-
Поиск подходящего драйвера устройства
-
Драйверы устройств в пространстве пользователя
-
Написание драйвера устройства ядра
-
Обнаружение конфигурации оборудования
Роль драйверов устройств
Как я уже упоминал в главе 4, Настройка и сборка ядра , одна из функций ядра состоит в том, чтобы инкапсулировать множество аппаратных интерфейсов компьютерной системы и представить их согласованным образом для программ пользовательского пространства. Ядро имеет структуру, предназначенную для упрощения написания драйвера устройства, который представляет собой фрагмент кода, который является посредником между ядром, расположенным выше, и оборудованием, расположенным ниже. Драйвер устройства может быть написан для управления физическими устройствами, такими как контроллер UART или MMC, или он может представлять виртуальное устройство, такое как нулевое устройство (/ dev / null) или виртуальный диск. Один драйвер может управлять несколькими устройствами одного типа.
Код драйвера устройства ядра работает с высоким уровнем привилегий, как и остальная часть ядра. Он имеет полный доступ к адресному пространству процессора и аппаратным регистрам. Он может обрабатывать прерывания и передачи DMA. Он может использовать сложную инфраструктуру ядра для синхронизации и управления памятью. Однако вы должны знать, что у этого есть обратная сторона; если что-то пойдет не так с ошибочным драйвером, это может действительно пойти не так и вывести систему из строя. Следовательно, существует принцип, согласно которому драйверы устройств должны быть максимально простыми, просто предоставляя информацию приложениям, в которых принимаются реальные решения. Вы часто слышите, как это выражается как отсутствие политики в ядре . Пользовательское пространство несет ответственность за установку политики, которая управляет общим поведением системы. Например, загрузка модулей ядра в ответ на внешние события, такие как подключение нового USB-устройства, является обязанностью программы пользовательского пространства, udev, а не ядра. Ядро просто предоставляет средства загрузки модуля ядра.
В Linux существует три основных типа драйверов устройств:
-
Символ :Это для небуферизованного ввода-вывода с богатым набором функций и тонким слоем между кодом приложения и драйвером. Это лучший выбор при реализации пользовательских драйверов устройств.
-
Заблокировать :У этого есть интерфейс, адаптированный для блочного ввода-вывода к и от запоминающих устройств. Существует толстый слой буферизации, предназначенный для максимально быстрого чтения и записи на диск, что делает его непригодным для чего-либо еще.
-
Сеть :Это похоже на блочное устройство, но используется для передачи и приема сетевых пакетов, а не дисковых блоков.
Существует также четвертый тип, который представляет собой группу файлов в одной из псевдофайловых систем. Например, вы можете получить доступ к драйверу GPIO через группу файлов в / sys / class / gpio, как я опишу позже в этой главе. Давайте начнем с более подробного рассмотрения трех основных типов устройств.
Символьные устройства
Символьные устройства идентифицируются в пользовательском пространстве с помощью специального файла, который называется узел устройства . . Это имя файла сопоставляется с драйвером устройства с использованием связанных с ним старшего и младшего номеров. Вообще говоря, основное число сопоставляет узел устройства с конкретным драйвером устройства, а младший номер сообщает драйверу, к какому интерфейсу осуществляется доступ. Например, узел устройства первого последовательного порта на ARM Versatile PB называется / dev / ttyAMA0, и он имеет старший номер 204 и младший номер 64. Узел устройства для второго последовательного порта имеет тот же старший номер, поскольку он обрабатывается тем же драйвером устройства, но младший номер - 65. Мы можем увидеть номера для всех четырех последовательных портов из списка каталогов здесь:
# ls -l / dev / ttyAMA * crw-rw ---- 1 root root 204, 64 января 1970 г. / dev / ttyAMA0crw-rw ---- 1 root root 204, 65 01 января 1970 / dev / ttyAMA1crw-rw ---- 1 корневой корень 204, 66 1 января 1970 г. / dev / ttyAMA2crw-rw ---- 1 корневой корень 204, 67 1 января 1970 / dev / ttyAMA3
Список стандартных основных и дополнительных номеров можно найти в документации ядра в Documentation / devices.txt. Список обновляется не очень часто и не включает устройство ttyAMA, описанное в предыдущем абзаце. Тем не менее, если вы посмотрите исходный код ядра в файле drivers / tty / serial / amba-pl011.c, вы увидите, где объявлены старший и младший номера:
#define SERIAL_AMBA_MAJOR 204 #define SERIAL_AMBA_MINOR 64
Если существует более одного экземпляра устройства, как в случае с драйвером ttyAMA, соглашение для формирования имени узла устройства состоит в том, чтобы взять базовое имя ttyAMA и добавить номер экземпляра от 0 до 3 в этом примере.
Как я упоминал в главе 5, Создание корневой файловой системы , узлы устройства можно создать несколькими способами:
-
devtmpfs:узел устройства создается, когда драйвер устройства регистрирует новый интерфейс устройства, используя базовое имя, предоставленное драйвером (ttyAMA) и номер экземпляра.
-
udev или mdev (без devtmpfs):по сути то же, что и с devtmpfs, за исключением того, что программа-демон пользовательского пространства должна извлекать имя устройства. из sysfs и создайте узел. Я расскажу о sysfs
-
mknod:если вы используете статические узлы устройств, они создаются вручную с помощью mknod.
У вас может сложиться впечатление от чисел, которые я использовал выше, что и старшие, и младшие числа являются 8-битными числами в диапазоне от 0 до 255. Фактически, начиная с Linux 2.6, старшее число имеет длину 12 бит, что дает допустимые числа. от 1 до 4 095, а младший номер - 20 бит, от 0 до 1 048 575.
Встроенный
- Роль встроенных систем в автомобилях
- Разнообразная роль эпоксидной смолы в производстве печатных плат устройств IoT
- Ключевые технологии усиливают растущую роль встраиваемого оборудования
- Обновления OTA для Embedded Linux, часть 2 - Сравнение стандартных систем обновлений
- Обновления OTA для Embedded Linux, часть 1 - Основы и реализация
- Драйверы для встроенных устройств Linux:обнаружение конфигурации оборудования
- Блог:понимание роли PDMS в области микрофлюидики
- От Интернета вещей до криптоджекинга:понимание новых угроз для мобильных устройств
- Введение во взлом встроенного оборудования устройств Интернета вещей
- Компоненты CAM и их роль в обработке с ЧПУ