Знакомство с devmaster
В нашей прошлой статье (https://openscaler.ru/2024/03/25/sysmaster/) мы рассмотрели sysmaster – «облегчённую» версию systemd, предназначенную для использования во встраиваемых устройствах. Сегодня мы рассмотрим devmaster — дополнение к sysmaster, представляющее из себя диспетчер устройств (аналог systemd-udev), предназначенное для управления устройствами в каталоге /dev.
Напомним, что диспетчер устройств является связующим звеном между программным обеспечением работающем в пространстве пользователя и базовыми физическими устройствами. devmaster предоставляет многоуровневые и масштабируемые возможности управления устройствами для распространенных операционных систем, основанных на ядре Linux.
Как программное обеспечение, devmaster состоит из демона, клиентского инструмента и динамической библиотеки. Демон devmaster использует механизмы ядра, такие как netlink, notify и sysfs, для мониторинга событий устройства и запуска задач обработки правил.
Клиентский инструмент devctl предоставляет набор команд CLI и общедоступных интерфейсов для отладки правил, управления демонами и запроса состояния устройства.
На следующем рисунке показана общая архитектура dev master:
devmaster написан на языке программирования Rust, обеспечивающем наиболее безопасное управление памятью.
Основные функции devmaster следующие:
1. Операции управляемые событиями: Механизмы кэширования очередей и рабочего пула используются для удовлетворения требований к событиям устройств с высокой степенью параллелизма. Кроме того, процессы пользовательского режима могут динамически уведомляться о готовности устройств.
2. Разделение механизмов и политик: Логика обработки устройств определяется как правила заданные в конфигурационных файлах, а не жестко задана в сервисном коде, что позволяет настраивать по требованию и гибко комбинировать.
3. Совместимость с экосистемой: dev master совместим с синтаксисом udev и широковещательным протоколом пользовательского режима udev. Существующие сервисы могут быть мигрированы на использование devmaster с низкими затратами.
Ну, довольно теории, переходим к практике!
Проверяем devmaster в деле
Все наши манипуляции мы проводим на OpenScaler 22.03 LTS SP3 (x86_64), на котором у нас уже установлена (смотри предыдущую статью) система инициализации sysmaster.
Для начала. давайте собственно установим devmaster и для этого выполним команду:
dnf install devmaster
И после этого сразу запустим devmaster с использованием знакомой нам уже утилиты sysmaster:
sctl enable devmaster.service
sctl start devmaster.service
После запуска devmaster создаст свою базу данных устройств (представляющую собой набор текстовых файлов) в каталоге /run/devmaster/data
. Мы можем просмотреть её используя привычные консольные утилиты.
Давайте теперь попробуем поработать с devmaster также, как мы привыкли работать с udev.
Для того, чтобы узнать в каких каталогах нам следует размещать наши самописные файлы rules обратимся к конфигурационному файлу /etc/devmaster/config.toml
Из него мы узнаём, что devmaster ищет файлы с rules в каталогах:
rules_d = ["/etc/devmaster/rules.d", "/lib/devmaster/rules.d", "/etc/udev/rules.d", "/run/udev/rules.d", "/lib/udev/rules.d"]
Давайте теперь обратимся к утилите devctl. Если запустить её с подкомандой help, то мы можем увидеть привычные нам по udevadm команды, такие как: info, monitor, trigger и т. д.
Давайте попробуем посмотреть информацию по какому-нибудь устройству:
# devctl info /dev/zero
P: /devices/virtual/mem/zero
M: zero
U: mem
D: c 1:5
N: zero
L: 0
E: MAJOR=1
E: DEVNAME=/dev/zero
E: TAGS=:devmaster:
E: DEVMODE=0666
E: SUBSYSTEM=mem
E: CURRENT_TAGS=:devmaster:
E: DEVPATH=/devices/virtual/mem/zero
E: MINOR=5
E: USEC_INITIALIZED=1711621744
и ещё вот так:
# devctl info --attribute-walk /dev/zero
Devctl info starts with the device specified by the devpath and then
walks up the chain of parent devices. It prints for every device
found, all possible attributes in the devmaster rules key format.
A rule to match, can be composed by the attributes of the device
and the attributes from one single parent device.
looking at device '/devices/virtual/mem/zero':
KERNEL=="zero"
SUBSYSTEM=="mem"
DRIVER==""
ATTR{power/control}=="auto"
ATTR{power/runtime_active_time}=="0"
ATTR{power/runtime_status}=="unsupported"
ATTR{power/runtime_suspended_time}=="0"
Да, мы видим такую же информацию, как если бы запускали udevadm.
Мы также можем запустить в отдельной консоли команду:
devctl monitor
А в другой попробовать триггернуть какое-нибудь устройство для проверки.
К примеру, тот же /dev/zero:
devctl trigger /dev/zero
И увидеть, что в monitor появились об этом сообщения вида:
KERNEL - the kernel uevent
USERSPACE - broadcasted by devmaster after successful process on device
KERNEL [] >> change /devices/virtual/mem/zero (mem)
USERSPACE [] >> change /devices/virtual/mem/zero (mem)
Давайте теперь, для примера, создадим своё собственное правило, по которому в каталоге /dev/test поместим символьные ссылки на блочные устройства, присутствующее в нашей системе.
Для этого нам предстоит написать своё правило (rule), которое мы должны разместить в каталоге /etc/devmaster/rules.d/
Приступим.
Создаём файл /etc/devmaster/rules.d/00-persist-storage.rules
с содержимым:
SUBSYSTEM!="block", GOTO="end"
IMPORT{builtin}=="blkid"
ENV{ID_FS_UUID_ENC}=="?*", SYMLINK+="test/$env{ID_FS_UUID_ENC}"
LABEL="end"
В этом правиле мы используем встроенную команду blkid для считывания UUID блочного устройства и создания программной ссылки для блочного устройства на основе UUID.
После запуска события устройства, имеющего файловую систему, в каталоге /dev/test
генерируется программная ссылка, соответствующая устройству.
Теперь нам надо перезапустить devmaster:
sctl stop devmaster
sctl start devmaster
(или мы можем воспользоваться одной командой: sctl restart devmaster
)
Проверим, что каталога /dev/test
пока ещё не существует.
Теперь давайте триггернём устройство /dev/sda1
# devctl trigger /dev/sda1
И проверяем каталог /dev/test
# ls -l /dev/test/
lrwxrwxrwx 1 root root 7 мар 29 13:56 9344-4BBC -> ../sda1
Да, у нас появилась символьная ссылка на /dev/sda1
, где именем ссылки выступает UUID из вывода команды blkid.
Теперь давайте триггернём /dev/sda2
# devctl trigger /dev/sda2
# ls -l /dev/test/
lrwxrwxrwx 1 root root 7 мар 29 13:57 8b880b42-b0e6-4076-bf8d-77f7dd889c5a -> ../sda2
lrwxrwxrwx 1 root root 7 мар 29 13:56 9344-4BBC -> ../sda1
А теперь давайте перезагрузим весь сервер, на котором мы проводим наши испытания.
После перезагрузки смотрим содержимое каталога /dev/test:
# ls -l /dev/test/
итого 0
lrwxrwxrwx 1 root root 7 мар 29 14:01 2bcae3e7-a422-4242-a36b-0cae357fc375 -> ../dm-1
lrwxrwxrwx 1 root root 7 мар 29 14:01 8b880b42-b0e6-4076-bf8d-77f7dd889c5a -> ../sda2
lrwxrwxrwx 1 root root 7 мар 29 14:01 8b97acbf-2dff-483f-b2dc-ff247d6453eb -> ../dm-0
lrwxrwxrwx 1 root root 7 мар 29 14:01 9344-4BBC -> ../sda1
lrwxrwxrwx 1 root root 7 мар 29 14:01 jrQ6UA-IOdT-O2Yo-YpR5-ckvT-6MLX-wzIfOa -> ../sda3
Как мы видим, при старте devmaster проверил все устройства и согласно правилу создал для них символьные ссылки.
Подводим итог
Сегодня мы рассмотрели devmaster, который является компонентом системы инициализации sysmaster и тоже, в свою очередь, заточен на применение в случаях, где и без того небольшой размер оперативной памяти является местом борьбы за оптимизацию и эффективность её использования. Поэтому, devmaster можно смело рассматривать (совместно с sysmaster) для применения на embedded устройствах.