Sysfs linux что это
Критический обзор значений атрибутов sysfs
Одной из многих запоминающихся строк знаменитого произведения Дугласа Адамса «Путеводитель для путешествующих по галактике автостопом» было обвинение, выдвинутое, вероятно, сторонниками «Энциклопедии Галактики», в том, что «Путеводитель автостопом» был «неравномерно отредактирован» и «содержит много отрывков, которые просто показались его редакторам хорошей идеей в то время». С небольшими изменениями, например, заменой «отредактировали» на «рецензировали», это описание кажется очень подходящим для ядра Linux и, несомненно, для многих других программ, открытых или закрытых, свободных или несвободных. Рецензирование в лучшем случае является «неравномерным».
Нетрудно найти жалобы по поводу того, что код ядра Linux недостаточно рецензируется или что нам нужно больше ревьюверов. Создание тегов типа «Reviewed-by» для патчей отчасти было попыткой решить эту проблему, предоставляя больше признания экспертам по рецензированию и, таким образом, поощряя больше людей поучаствовать в этой роли.
Однако с тем же успехом можно найти жалобы на слишком большое количество рецензий в тех случаях, когда разработчики не могут продвинуться в развитии какой-либо функции, потому что каждый раз, когда они публикуют новую редакцию, кто-нибудь снова начинает жаловаться на что-то ещё, и так, в погоне за совершенством, упускают хорошее. Аналогично, хотя в последнее время это не кажется проблемой, бывали случаи, когда большое количество замечаний сводилось к жалобам на несоответствие пробелов и орфографические ошибки — вещи, которые можно исправить, но не стоит хоронить под ними ценный вклад.
Найти правильную тему, правильный уровень и правильный форум для рецензирования нелегко (а время на это найти может быть еще труднее). Эта статья не ставит своей целью прямое решение данных вопросов, а скорее представляет образец рецензирования — конкретной темы на конкретном уровне на конкретном форуме, в надежде, что он окажется полезным. Тема, выбранная во многом потому, что в последнее время вашему автору приходится работать с ней, не имея полного понимания, — это » sysfs «, виртуальная файловая система, предоставляющая доступ к некоторым внутренним компонентам ядра Linux. И, в частности, файлы атрибутов, которые раскрывают мелкие детали этого доступа.
Выбранный подход — это высокоуровневый или целостный взгляд, спрашивающий, соответствует ли реализация целям, и в то же время — уместны ли цели. И форумом, разумеется, будет настоящая публикация.
Sysfs и файлы атрибутов
Sysfs имеет интересную историю и ряд целей проектирования, в которых стоит разобраться, но ни одна из них не будет рассмотрена здесь, кроме как в той мере, в какой они отражают конкретно выбранную тему: файлы атрибутов. Ключевой целью дизайна, связанной с файлами атрибутов, является условие — почти мантра — «один файл — одно значение» или иногда «один элемент на файл». Идея заключается в том, что каждый файл атрибутов должен содержать только одно значение. Если требуется много значений, то следует использовать несколько файлов.
На фоне этой дезорганизации и сопутствующих трудностей, которые возникали при добавлении новых полей, чтобы это не нарушало работу приложений, в sysfs была объявлена новая политика — один элемент на файл. На самом деле, в своей превосходной (хотя теперь уже несколько устаревшей) статье о Ядре модели драйвера Грег Кроа-Хартман даже утверждал, что это правило «соблюдается» (см. боковую панель » sysfs «).
Как можно догадаться, ответы будут «нет», «нет» и «нет», но объяснение будет гораздо более познавательным, чем сам ответ.
Выполняется ли оно?
Лучший способ проверить, соблюдается ли правило, — это изучить содержимое sysfs : хранятся ли в файлах простые значения или что-то большее? В качестве весьма грубой оценки степени сложности содержимого файла атрибутов sysfs можно выполнить простую команду:
Обработка этих результатов на ноутбуке автора (Linux 2.6.32) показывает, что из 9254 файлов 1189 пустые, а 7168 содержат только одно слово. Вполне резонно предположить, что они представляют только одно значение (хотя многие из пустых файлов, вероятно, предназначены только для записи, и этот механизм не дает информации о том, какое значение или значения могут быть записаны). Остается 897 (почти 10%), которые требуют дальнейшего изучения. Они варьируются от двух слов (487 случаев) до 297 слов (один случай).
В то время как файлов почти 900, базовых имен меньше 100. Если отфильтровать некоторые общие шаблоны (например, gpe%X ), то количество отдельных атрибутов приблизится к 62, то есть к числу, которое вполне можно исследовать вручную (с небольшой помощью некоторых сценариев). Некоторые из этих многословных файлов атрибутов содержат данные не в формате ASCII и поэтому почти наверняка являются единичными значениями с точки зрения разумной логики. Другие содержат строки, для которых пробел является законным символом, например, «Dell Inc.», «порт i8042 KBD» или «write back». Поэтому они не являются явным отклонением от правила.
Существует небольшой класс файлов, в которых единственный элемент, хранящийся в файле, имеет перечислимый тип. Обычно в таких случаях файл содержит все возможные значения, которые перечислены в списке, что по-прежнему соответствует правилу «один элемент в файле». Однако есть три вариации на эту тему:
В некоторых случаях, таких как атрибут » queue/scheduler » блочного устройства или атрибут » trigger » светодиодного устройства, перечисляются все возможные опции, при этом активный в данный момент вариант заключен в скобки, таким образом:
Во втором варианте есть два файла, один содержит список возможностей, как в случае » cpufreq/scaling_available_governors «, а другой — выбранное в данный момент значение, » cpufreq/scaling_governor «.
Наконец, и это просто может оказаться особым случаем одного из вышеперечисленных, у нас есть » /sys/power/state «, для которого нет текущего значения, поэтому он просто содержит список возможных значений.
Это все примеры файлов атрибутов, которые явно содержат только одно значение или элемент, но используют несколько слов для описания этих значений. Они представляют собой ложноположительные результаты нашего упрощенного инструмента для поиска сложных значений атрибутов.
В качестве последнего примера несоблюдения правил: каталог PCI-устройств для беспроводной сети (Intel 3945) в этом ноутбуке содержит файл под названием » statistics «, который содержит шестнадцатеричный дамп 240 байт данных, с расшифровкой ASCII в конце каждой строки, типа:
Итак, ответом на наш вводный вопрос будет “нет”, так как правило “один элемент на файл” никоим образом не применяется. Конечно, подавляющее большинство файлов атрибутов содержат только один элемент, и это хорошо. Но есть и такие, которые содержат несколько значений, причем разными способами. И это число, скорее всего, будет только расти, поскольку люди либо копируют данные неудачные примеры, либо находят новые случаи использования, которые не соответствуют существующим шаблонам, и изобретают новые подходы, которые не учитывают целостную картину.
Достаточно ли этого правила?
Аналогичная проблема возникает и с простыми числовыми значениями, которые представляют измеримые элементы, такие как размер хранилища или время. Было бы хорошо, если бы они передавались с использованием стандартных единиц, возможно, байтов и секунд. Но мы видим, что это не так. Объем памяти иногда указывается в байтах ( /sys/devices/system/memory/block_size_bytes ), иногда в секторах ( /sys/class/block/*/size ), а иногда в килобайтах ( block/*/queue/read_ahead_kb ).
Как показывают эти конкретные примеры, одним из способов избежать двусмысленности является включение названия единиц измерения (здесь байты или кб) как части имени атрибута, что известно как Венгерская нотация. Однако это далеко не всегда применяется единообразно, и приведенные выше примеры являются скорее исключением, чем правилом.
И еще есть истинностные значения: Вкл, вкл, 1, Выкл, выкл, 0.
Таким образом, похоже, что ответ на наш второй вопрос тоже «нет», хотя в этом случае трудно быть уверенным, поскольку нет четко сформулированной цели, по которой можно было бы все это оценивать. Если же нашей целью является высокая степень единообразия при представлении значений в атрибутах, то мы явно не достигаем ее.
Всегда ли это требование имеет смысл?
Таким образом, основополагающий принцип «один элемент на файл» не выполняется единообразно, и его недостаточно, чтобы избежать ненужных несоответствий. Но если бы его применяли единообразно, дал бы он действительно то, что мы хотим, или же он слишком упрощен и расплывчат, чтобы быть полезным в качестве строгого правила?
Хорошим местом для начала изучения этого вопроса является атрибут » capabilities/key » устройств «ввода». Содержимое этого файла представляет собой битовую карту со списком событий нажатия клавиш, которые может генерировать устройство ввода. Битовая карта представлена в шестнадцатеричном формате с пробелом через каждые 64 бита. Очевидно, что это одно значение — битовая карта — но это также и массив битов. Или, может быть, массив » long «. Является ли это несколькими значениями в одном атрибуте?
Хотя это тривиальный пример, который, несомненно, все принимают за одно значение, несмотря на то, что оно имеет длину много бит, нетрудно найти примеры, которые не так однозначны. Каждое блочное устройство имеет атрибут под названием » inflight «, который содержит два числа: количество запросов на чтение, которые находятся в процессе выполнения (были отправлены, но еще не выполнены), и количество запросов на запись, которые находятся в процессе выполнения. Это единый массив, как в битовой карте, или два отдельных значения? Реализация » inflight » в виде двух отдельных атрибутов, тем самым четко следуя правилу, не потребует больших затрат, но, возможно, и пользы от этого тоже будет немного.
Атрибут » cpufreq/stats/time_in_state » идет на шаг дальше. Он содержит пары, по одной на строку, частот процессора (приятно, что в Гц) и общее время, проведенное на этой частоте (к сожалению, в микросекундах). Это скорее словарь, чем массив. Поразмыслив, можно сказать, что это действительно то же самое, что и предыдущие два примера. И для «key», и для » inflight » ключ — это перечислимый тип, который просто отображается на последовательность целых чисел, начинающуюся с нуля. Таким образом, в каждом случае мы видим словарь. В последнем случае ключи являются явными, а не неявными.
Если мы сравним этот последний пример с каталогом » statistics » в любом устройстве » net » ( net/*/statistics ), то увидим, что вполне возможно поместить индивидуальную статистику в отдельные файлы. Если бы эти 23 различных значения были помещены в один файл, по одному на строку с метками, вряд ли кто-то согласился бы с тем, что в этом файле находится только один элемент.
Следствием этих исследований, похоже, является то, что мы должны разрешить хранение структурированных данных в атрибутах, поскольку нет четкой границы между структурированными и неструктурированными данными. «Один элемент на файл» — это отличная эвристика, которая в большинстве случаев хорошо нас ориентирует, но, как мы видели, есть много случаев, когда разработчики обнаруживают, что она не подходит, поэтому отступают от правил с удручающей непоследовательностью.
Возможно даже, что твердо установленное правило оказывает здесь негативное влияние. Столкнувшись с твердой уверенностью в том, что набор чисел действительно образует один атрибут, и с четко сформулированным правилом о недопустимости многозначных атрибутов, разработчики часто идут по пути наименьшего сопротивления — тихо реализуют многоэлементный атрибут, никому не говоря об этом. Существует большая вероятность того, что такой код не будет отрецензирован до тех пор, пока не станет слишком поздно вносить изменения. Это может привести к тому, что несколько разработчиков начнут решать одну и ту же проблему разными способами, тем самым усугубляя ее еще больше, хотя всего этого и должно было бы избежать выполнение правила.
Итак, чтобы ответить на наш третий вопрос, «нет», нужно отметить, что правило «один элемент на файл» не всегда имеет смысл, потому что не всегда ясно, что считать «одним элементом», а наличие таких мест неопределенности — это дыры для хаоса, который может закрасться в наше ядро.
Можем ли мы сделать лучше?
Рецензия, которая находит проблемы, даже не предлагая их устранения, — действительно плоха. Выше был указан ряд проблем, а теперь мы, как минимум, обсудим решения.
Проблема существующих атрибутов, которые неуместно сложны или непоследовательны в своем форматировании, не предполагает быстрого решения. Невозможно просто изменить формат. В лучшем случае можно предоставить новые способы доступа к той же информации, а затем отказаться от старых атрибутов. Часто утверждается, что как только что-то попадает в интерфейс пространства ядра-пользователя (который включает в себя все sysfs ), оно не может быть изменено. Однако существование CONFIG_SYSFS_DEPRECATED_V2 опровергает это утверждение. Политика, которая разрешает и поддерживает обесценивание и удаление атрибутов sysfs на постоянной основе, может причинять некоторую боль, но в долгосрочной перспективе будет полезна для ядра, особенно если мы ожидаем, что наши внуки продолжат разработку Linux.
Ваш автор в настоящее время размышляет над тем, как лучше передать список «известных плохих блоков» на устройствах RAID (Redundant Arrays of Inexpensive Disks) между ядром и пользовательским пространством. sysfs — очевидное место для управления данными, но иметь один файл на блок было бы глупо, а единственный файл со списком всех плохих блоков достигнет максимума в одну страницу примерно при 300-400 записях, что намного меньше, чем нам хочется поддерживать. Поддержка структурированных атрибутов sysfs очень помогла бы здесь.
Последняя проблема — как обеспечить соблюдение любых правил, которые мы придумаем. Даже об очень простом правиле, которое легко и часто повторяется и о котором многие слышали, недостаточно лишь просто быть осведомленным; важно заставить людей следовать этому правилу. В этом мы только что убедились.
Если бы большая часть sysfs была переведена на использование интерфейса, обеспечивающего стандартизированный внешний вид, стало бы довольно легко найти нестандартные атрибуты и затем либо оспорить их, либо улучшить стандартный интерфейс для их поддержки.
В заключение
Всех желающих приглашаем на открытый урок «Работа с Git, основы и уверенное использование». На уроке вы детальнее погрузитесь в описание внутренней архитектуры git: файлы, деревья, коммиты и теги.
>> РЕГИСТРАЦИЯ
Если вам интересно развитие в этой сфере с нуля до pro, рекомендуем ознакомиться с учебной программой специализации.
Национальная библиотека им. Н. Э. Баумана
Bauman National Library
Персональные инструменты
sysfs
sysfs – виртуальная файловая система операционной системы Linux, которая экспортирует в пространство пользователя через виртуальные файлы информацию о различных подсистемах ядра, подключенных устройствах и соответствующих им драйверах. В дополнение к экспорту информации о различных устройствах и подсистемах виртуальные файлы используются для их конфигурации.
Содержание
История
К тому времени новая модель драйверов была объединена в версии ядра 2.5.1 и получила название driverfs, которое лучше отражало ее функциональность. В течение следующего года разработки версии 2.5, инфраструктурные возможности модели driverfs стали казаться полезными для других подсистем. Для центрального управления объектами был разработан механизм kobjects, а driverfs преобразовался в sysfs.
Монтирование sysfs
sysfs монтируется как любая другая файловая система в оперативной памяти:
Нужно иметь ввиду, что sysfs монтируется в директорию /sys по-умолчанию.
Навигация в sysfs
Поскольку sysfs это просто набор директорий, файлов и символических ссылок, она легко управляется с помощью обычных утилит оболочки (рекомендуется использовать tree(1)).
На верхнем уровне монтирования sysfs находится число директорий. Эти директории представляют основные подсистемы, зарегистрированные с помощью sysfs. Директории создаются во время запуска системы, когда происходит регистрация подсистем ядром kobject. После инициализации, они начинают открывать объекты, зарегистрированные в рамках соответствующих директорий.
block
Директория block содержит поддиректории для каждого блока устройства, которое было обнаружено в системе. В директории каждого блока устройства находятся атрибуты, описывающие множество параметров, включая размер устройства и соответствующий ему номер dev_t. Там же находится символическая ссылка, которой сопоставляется соответствующее устройство из физического дерева устройств. Так же, существует директория представляющая интерфейс планировщика ввода/вывода. Этот интерфейс обеспечивает статистическими данными о очереди запросов устройств и некоторые перестраиваемые функции, которые пользователь или администратор могут использовать для оптимизации производительности. Каждый раздел каждого блока устройства представлен как поддиректория блока устройства. Атрибуты в этих директориях только для чтения.
Директория bus содержит поддиректории для каждого типа физической шины, которые поддерживают регистрацию в ядре (либо статически скомпилированы, либо загружаются через модуль).
Директория drivers содержит директории для драйверов каждого устройства, зарегистрированного на этом типе шины. Внутри каждой директории драйверов атрибуты позволяют просматривать и управлять параметрами драйвера и символическими ссылками, к которым привязаны драйвера соответствующих устройств из физического дерева устройств.
class
Директория class содержит представления каждого класса устройств, зарегистрированного в ядре. Класс устройства описывает функциональный тип устройства.
Каждый класс устройства содержит поддиректории для каждого класса объекта, который определен и зарегистрирован с этим классом устройства. Для большинства классов объектов устройств, их директории содержат символические ссылки на директории устройства и драйвера. Физическое устройство может содержать несколько объектов класса, которые выполняют разные логические функции. Каждый класс устройства и класс объекта может содержать атрибуты с параметрами, которые описывают или контролируют класс объекта.
devices
Директория devices представляет собой глобальную иерархию устройств. Она содержит все физические устройства, которые были обнаружены шинами, типы которых зарегистрированы в ядре. Родственные устройства представляют собой цепочку устройств, где каждое последующее устройство физически или электрически подчиняется предыдущему. Но существует два типа устройств, являющихся исключениями: платформенные устройства и системные устройства. Платформенные устройства это периферийные устройства, присущие данной платформе. Обычно они имеют порты вводы/вывода или MMIO, которые находятся в определенном месте. Системные устройства не принадлежат к периферийным, но являются неотъемлемой частью системы. Во многом, они не имеют ничего общего с другими устройствами. Они имеют доступ к аппаратной конфигурации, но не имеют возможности передавать данные. Обычно, системные устройства не привязаны к драйверам, но, по-крайней мере для представленных в sysfs, имеется конкретный архитектурный код, который настраивает их и обрабатывает в качестве объекта экспорта.
firmware
Директория firmware содержит интерфейсы для просмотра и управления определенными объектами прошивки и их атрибутами. Прошивка, в этом случае, ссылается на платформо-ориентированный код, который исполняется при запуске системы. Каждая директория содержит множество объектов и атрибутов специфичных для прошивки.
module
power
Интерфейс ядра
Функции sysfs видимые для ядра разделяются на три категории, зависящие от типа объекта, который они экспортируют в пользовательское пространство:
Также есть две подкатегории экспорта, атрибуты которых были разработаны для пользователей нуждающихся в экспорте других файлов, в частности ASCII файлов:
В файловой системе результаты экспорта обеих этих категорий представлены в виде файлов.
Первый параметр всех функций sysfs это kobject, с которым проводится манипуляции. Ядро sysfs предполагает, что этот kobject будет валидным на протяжении времени работы функции. Вызывающий всегда несет ответственность за обеспечение валидности и неизменности объекта в течение всего вызова sysfs. Все функции sysfs должны вызываться из контекста процесса. Они также не должны вызваться с какими-либо спинлоками, так как большинство из них напрямую принимают семафоры и все вызовы функций виртуальной файловой системы, которые также принимают семафоры и могут стать причиной остановки процесса.
Объекты ядра
Объекты ядра экспортируются как директории через sysfs. Функции для работы с объектами ядра:
Объявление функции | Назначение |
---|---|
int sysfs_create_dir(struct kobject ∗ k); | Создание директории |
void sysfs_remove_dir(struct kobject ∗ k); | Удаление директории |
int sysfs_rename_dir(struct kobject ∗, const char ∗new_name); | Изменение имени директории |
У параметра kobject существует два основных поля, за валидностью которых и нужно следить:
При создании директории, эти параметры контролируют где будет создана директория и что запустило создание этой директории. Расположение новой директории определяется по параметру k->parent ; она создается как ее поддиректория. Если параметр k->parent пуст, то директория создастся на самом верхнем уровне иерархии. Во всех случаях, подсистема (кроме драйвера низкого уровня) сама заполнит эту область информацией известной об объекте, если объект зарегистрирован в подсистеме. Это обеспечивает простой механизм создания пользовательского представления внутреннего дерева объектов.
В случае удаления директории, также удалятся все объекты, принадлежащие данной директории, в том числе и файлы.
При вызове функции изменения имени директории, sysfs выделяет новый объект dentry для kobject и вызывает процедуру koject для изменения имени объекта. Если переименование прошло успешно функция вернет 0. В других случаях, функция возвращает отрицательное значение, соответствующее идентификатору ошибки.
Объекты атрибутов
Объявление функции | Назначение |
---|---|
int sysfs_create_file(struct kobject ∗, const struct attribute ∗); | Создание файла |
void sysfs_remove_file(struct kobject ∗, const struct attribute ∗); | Удаление файла |
int sysfs_update_file(struct kobject ∗, const struct attribute ∗); | Обновление файла |
При создании атрибута, для определения его имени используется поле name структуры и поле mode для установки режима доступа к файлу. Директория создания файла определяется локацией kobject. Поле owner структуры используется как счетчик ссылок для того, чтобы знать когда файл доступен. Файловые операции над атрибутами, которые вызывает виртуальная файловая система устанавливаются sysfs. Это позволяет sysfs ловить каждый запрос доступа и выполнить необходимые действия. Когда файл открыт, sysfs инкрементирует счетчик ссылок и kobject, представленного директорией где расположен атрибут, и модуля, содержащего код атрибута.
Если данные атрибута изменены, ядро может сообщить процессу, что пользовательское пространство может ждать обновления, путем изменения временную отметку файла используя функцию обновления.
Объекты отношений
Отношение между двумя объектами в sysfs может быть выражено символической ссылкой. Функции для работы с символическими ссылками:
Объявление функции | Назначение |
---|---|
int sysfs_create_link(struct kobject ∗kobj, struct kobject ∗target,char ∗name); | Создание символической ссылки |
void sysfs_remove_link(struct kobject ∗, char ∗name); | Удаление символической ссылки |
Группы атрибутов
Интерфейс группы атрибутов это простой интерфейс для добавления и удаления атрибутов за один вызов. Работа с группой атрибутов обеспечивается struct attribute_group с набором методов:
Объявление функции | Назначение |
---|---|
int sysfs_create_group(struct kobject ∗, const struct attribute_group ∗); | Создание группы атрибутов |
void sysfs_remove_group(struct kobject ∗, const struct attribute_group ∗); | Удаление группы атрибутов |
Группа атрибутов представляет собой простой массив атрибутов, определенный полем attrs. sysfs может создать поддиректорию для хранения группы атрибутов. При добавлении атрибутов, значение возвращаемого результата функции зависит от каждого. Если добавление хотя бы одного атрибута нарушится, предыдущие добавленные атрибуты удалятся и вернется код ошибки. При удалении группы атрибутов, все внутренние атрибуты также будут удалены. Если для хранения группы sysfs создала поддиректорию, то она также будет удалена.
Бинарные файлы
Бинарные файлы это специальный класс файлов, которые могут быть экспортированы через sysfs, используя struct bin_attribute и ее методы:
Объявление функции | Назначение |
---|---|
int sysfs_create_bin_file(struct kobject ∗ kobj, struct bin_attribute ∗ attr); | Создание бинарного файла |
int sysfs_remove_bin_file(struct kobject ∗ kobj, struct bin_attribute ∗ attr); | Удаление бинарного файла |
Структура нужна, чтобы экспортировать бинарные данные, которые легче форматировать и обрабатывать в более гибкой среде, такой как контекст процесса пользовательского пространства, так как они имеют известный заданный формат.