Sysfs linux что это

Обновлено: 06.07.2024

Что такое файловая система? Согласно высказыванию одного из первых мэйнтейнеров Linux и автора популярных книг - Роберта Лава, файловая система - это иерархическое хранилище данных, придерживающиеся определённой структуры.

Однако, это описание одинаково хорошо подходит как для VFAT (Virtual File Allocation Table), так и для Git, Cassandra и других баз данных. Так что же отличает файловую систему? В этой статье мы попытаемся ответить на этот вопрос, а также разобраться что такое виртуальные файловые системы.

Основы файловых систем

Ядро Linux требует, чтобы во всём, что считается файловой системой были реализованы методы open(), read(), и write() для постоянных объектов, у которых есть имена. С точки зрения объективно ориентированного программирования, ядро считает файловую систему абстрактным интерфейсом, в котором определены эти виртуальные функции без реализации. Таким образом реализация файловой системы на уровне ядра называется VFS (Virtual Filesystem).


Мы можем открыть, прочитать и записать в файл.

Термин VFS лежит в основе всем известного утверждения о том, что в Unix-подобных системах всё является файлом. Подумайте о том, насколько странно, что приведенная выше последовательность действий с файлом /dev/console работает. На снимке показан интерактивный сеанс Bash в виртуальном терминале TTY. При отправке строки устройству виртуальной консоли, она появляется на виртуальном экране. VFS имеет и другие, даже более странные свойства. Например, в таких файлах можно выполнять поиск.

В таких популярных файловых системах как Ext4, NFS и даже в подсистеме /proc реализованы три основные функции в структуре данных на языке Си, которая называется file_operations. Кроме того, некоторые файловые системы расширяют и переопределяют функции VFS подобным объективно ориентированным способом. Как утверждает Роберт Лав, абстракция VFS позволяет пользователям Linux копировать файлы из других операционных систем или абстрактных объектов, таких как каналы не беспокоясь об их внутреннем формате данных. В пространстве пользователя с помощью системного вызова read() процессы могут копировать содержимое файла в структуры ядра из одной файловой системы, а затем использовать системный вызов write() в другой файловой системе, чтобы записать полученные данные в файл.

Определения функций, относящиеся к VFS находятся в файлах fs/*.c в исходном коде ядра. Подкаталоги fs/ же содержат различные файловые системы. Ядро также содержит объекты, похожие на файловые системы, это cgroups, /dev и tmpfs, которые нужны на раннем этапе загрузки системы и поэтому определены в подкаталоге исходников init/. Обратите внимание, что они не вызывают функции большой тройки из file_operations, зато они могут непосредственно читать и записывать в память.

На схеме ниже наглядно показано, как из пространства пользователя можно получить доступ к большинству файловых систем. На рисунке нет каналов, таймера POSIX и dmesg, но они тоже используют методы из структуры file_operations и работают через VFS:


Существование VFS способствует повторному использованию кода, поскольку основные методы для работы с файловыми системами не переопределяются в каждой файловой системе. Это широко используемая практика, однако если в таком коде есть ошибки, то от них страдают все реализации, использующие общие методы.

Самый простой способ вывести все виртуальные файловые системы, это выполнить такую команду:

mount | grep -v sd | grep -v :/

Она выведет все смонтированные файловые системы, которые не связанны с физическим или сетевым диском. Оной из первых точек монтирования виртуальных файловых систем будет /tmp. Так почему не рекомендуется хранить содержимое /tmp на диске? Потому что файлы из /tmp временные, а постоянные хранилища намного медленнее памяти, где находится tmpfs. Кроме того, физические устройства более подвержены износу от частой записи, в отличие от оперативной памяти. И наконец, файлы в /tmp могут содержать конфиденциальную информацию, поэтому их лучше удалять при каждой перезагрузке.

/proc и /sys

Помимо /tmp, виртуальные файловые системы, с которыми знакомо большинство пользователей Linux - это /proc и /sys (/dev полагается на общую память и не поддерживает file_operations). Но зачем аж две? Давайте разбираться.

Файловая система procfs предоставляет моментальный снимок состояния ядра и процессов, которые оно контролирует в пространстве пользователя. Кроме того, в /proc ядро делает доступной информацию о прерываниях, виртуальной памяти и планировщике. А ещё в /proc/sys размещены параметры, которые можно настроить из пространства пользователя с помощью команды sysctl. Состояние и статистика по каждому процессу находятся в директориях /proc/<PID>.


/proc/meminfo - пустой файл, но тем не менее, он содержит информацию о памяти

Поведение файлов в /proc показывает, насколько виртуальные файловые системы могут отличаться от, тех, у которых есть файлы на диске. С одной стороны, файл /etc/meminfo содержит информацию, выводимую командой free. Но с другой стороны, он пустой! Как такое может быть. Ситуация напоминает знаменитую статью, написанную физиком Корнельского университета Дэвидом Мермином в 1985 году под названием Есть ли Луна когда никто не смотрит? На самом деле ядро собирает статистику о памяти, когда процесс запрашивает её из /proc. И на самом деле в файлах из /proc ничего нет, когда никто не смотрит. Как сказал Мермин, "Фундаментальная квантовая доктрина состоит в том, что измерение, как правило, не выявляет ранее существовавшее значение измеряемого свойства.

Кажущаяся пустота /proc имеет смысл, поскольку доступная информация динамическая и актуальная на момент получения. Ситуация с файловой системой /sys. Давайте сравним сколько файлов, размером хотя бы один байт, находятся в /proc и /sys:


В procfs такой файл только один - это конфигурация ядра, которую надо генерировать только один раз во время загрузки. С другой стороны в каталоге /sys содержится много файлов большого размера, но большинство из них составляют одну страницу памяти. Обычно файлы из sysfs содержат одно число или строку, в отличие от таблиц информации, например, из /proc/meminfo.

Цель sysfs - предоставить доступ для чтения и записи свойств так называемых объектов kobjects в пользовательском пространстве. Единственная цель kobject - подсчёт ссылок, когда последняя ссылка на kobject будет удалена, система освободит ресурсы, связанные с ним. К тому же, /sys/ составляет основную часть стабильного ABI ядра для пользовательского пространства, которую никто и ни при каких обстоятельствах не может сломать. Но это не значит, что файлы в sysfs статичны. Это бы противоречило подсчёту ссылок.

Стабильность ABI ограничивает то, что может появится в /sys, а не то, что на самом деле есть в любой конкретный момент. Перечисление разрешений на файлы в sysfs дает представление о том, что настраиваемые параметры устройств, модулей и файловых систем можно прочитать и изменить. По логике procfs тоже должна быть частью стабильного ABI ядра, однако в документации об этом ничего не сказано.


Файлы в sysfs можно читать или записывать или всё вместе. Здесь 0 означает, что SSD не извлекаем.

Слежение за VFS

Самый простой способ узнать как ядро управляет файлами в sysfs - это посмотреть на это всё в действии. А самый простой способ это сделать на ARM64 или x86_64 - это использование eBPF. eBPF (extended Berkeley Packet Filter) - состоит из виртуальной машины, работающей на уровне ядра, к которой привилегированные пользователи могут обращаться из командной строки. Исходный код ядра показывает читателю как ядро может что-то сделать. Инструменты eBPF показывают как на самом деле всё происходит.

К счастью, начать работу с eBPF довольно просто с помощью инструментов bcc, для которых доступны пакеты в множестве дистрибутивов. Инструменты bcc - это скрипты на Python с небольшими фрагментами кода на Си, а это значит, что любой кто знаком с этим языком может их модифицировать. На данный момент существует около 80 скриптов на Python в bcc, поэтому каждый найдёт то, что ему надо.

Чтобы получить общее представление о работе VFS в работающей системе используйте простые скрипты vfscount и vfsstat, которые покажут, что каждую секунду выполняются десятки вызовов vfs_open() и подобных функций:

В качестве менее общего примера, давайте посмотрим что происходит, когда к работающей системе подключается USB накопитель:


Когда USB-накопитель вставлен, появляется трассировка вызовов ядра, показывающая что один из потоков kworker с PID 7711 создал файл с именем events в sysfs. При попытке отслеживать вызов sysfs_remove_files() вы увидите, что извлечение флешки приводит к удалению файла events в соответствии с идеей отслеживания ссылок. Отслеживание sysfs_create_link() во время подключения USB накопителя показывает что создается не менее 48 ссылок.

Зачем же нужен файл events? Используя инструмент cscope можно найти функцию __device_add_disk(), которая вызывает функцию disk_add_events(). А та в свою очередь может записать в файл "media_change" или "eject request". Здесь ядро сообщает в пользовательское пространство о появлении или исчезновении диска. Это намного информативнее, чем просто анализ исходников.

Файловые системы только для чтения

Никто не выключает сервер или компьютер, просто отключив питание. Почему? Потому что примонтированные файловые системы на физических устройствах могут выполнять запись и структуры данных файловой системы могут быть не полностью перенесены на диск. Когда такое происходит, вам придется при следующей загрузке подождать восстановления файловой системы с помощью fsck, а в худшем случае вы даже можете потерять данные.

Тем не менее, вы наверное слышали, что многие встраиваемые устройства, такие как маршрутизаторы, термостаты и даже автомобили работают под Linux. У многих из этих устройств нет пользовательского интерфейса и их невозможно корректно выключить. Представьте автомобиль, основной компьютер которого полностью отключается, когда разряжается батарея. Как тогда быстро включить компьютер, когда двигатель снова заработает и батарея восстановит заряд? Ответ прост. IoT устройства используют корневую систему в режиме только для чтения или коротко ro-rootfs.

Такой подход даёт несколько преимуществ, которые менее очевидны чем неповреждаемость. Одна из них - вирусы не могут выполнять запись в /user или /lib если ни один процесс Linux не может выполнять туда запись. Во вторых это обеспечивает удобную поддержку удалённых устройств, поскольку они имеют такую же файловую систему как и тестовые образцы. Самое важное обстоятельство такого подхода - разработчикам приходится решать на этапе проектирования какие компоненты системы должны быть неизменяемыми. Работа с ro-rootfs иногда может быть очень сложной, но преимущества компенсируют недостатки.

Создания таких файловых систем требует дополнительных усилий от разработчиков и здесь снова на помощь приходит VFS. Linux требует, чтобы файлы в /var были доступны для записи, кроме того, множество приложений будут пытаться создавать скрытые файлы в домашней папке. Решением для файлов конфигурации в домашнем каталоге моет быть их предварительное создание. В каталог /var можно монтировать отдельный раздел, доступный для записи, тогда как корень будет все ещё доступен только для чтения. Другая же альтернатива - использование bind и overlay монтирования.

Bind и overlay монтирование

Лучше всего про монтирование файловых систем и про bind монтирование в частности можно узнать выполнив такую команду:

Bind и overlay монтирование позволяет разработчикам встраиваемых систем и системным администраторам создавать файловую систему, доступную по определённому пути, а потом делать её доступной приложениям по совсем другому пути. Для встраиваемых систем подразумевается что можно хранить файлы из /var на устройстве доступном только для чтения, но наложить на /var tmpfs, так чтобы приложения могли туда писать если им это надо. При перезагрузке все изменения в /var будут утеряны. Overlay монтирование позволяет объединить tmpfs и обычную файловую систему так, чтобы в ней можно было изменять файлы, а bind монтирование позволяет сделать доступными для записи пустые папки с tmpfs в ro-rootfs. Хотя overlayfs - это отдельная файловая система, bind монтирование выполняется с помощью VFS.

Исходя из всего этого, не удивительно, что контейнеры Linux активно используют overlay и bind монтирование. Давайте посмотрим что происходит, когда мы запускаем контейнер с помощью systemd-nspawn. Будем использовать инструмент mountsnoop из набора bcc:


Осталось посмотреть что произошло:


Здесь systemd-nspawn размещает нужные файлы из procfs и sysfs хоста в контейнер. Здесь помимо флага MS_BIND, означающего bind-монтирование есть флаги, которые настраивают связь при изменениях файлов процессами контейнера или хоста. Например, файловая система может автоматически отображать изменения в контейнере или скрывать их.

Выводы

Понимание внутреннего устройства Linux может показаться невыполнимой задачей, поскольку само ядро содержит огромный объем кода и это не считая приложений пространства пользователя и библиотеки glibc. Один из способов достичь прогресса - прочитать исходный код одной из подсистем ядра, обращая внимание на системные вызовы, которые используются пространством пользователя, а также на основные внутренние интерфейсы ядра, вроде структуры file_operations.

Структура file_operations - это то, что делает концепцию "Всё есть файл" работающей, поэтому изучение информации о ней особенно интересно. Исходные файлы ядра в каталоге fs/ представляют собой реализацию виртуальных файловых систем, которые представляют из себя слой прокладки для взаимодействия между физическими устройствами и популярными файловыми системами. Bind и overlay монтирование - это магия VFS, которая делает возможным использование Linux на IoT устройствах и контейнеры. Инструменты eBPF вместе с изучением исходного кода ядра, делают исследование ядра проще чем когда либо.

Всем привет! Мы продолжаем запуски новых потоков по уже полюбившимся вам курсам и сейчас спешим сообщить о том, что у нас стартует новый набор по курсу «Администратор Linux», который запустится в конце апреля. К этому событию и будет приурочена новая публикация. С оригиналом материала можно ознакомиться тут.

Виртуальные файловые системы выполняют роль некой волшебной абстракции, которая позволяет философии Linux говорить, что «всё является файлом».


Что такое файловая система? Опираясь на слова одного из первых контрибьюторов и авторов Linux Робера Лава, «Файловая система – это иерархическое хранилище данных, собранное в соответствии с определенной структурой». Как бы то ни было, это определение в равной мере хорошо подходит для VFAT (Virtual File Allocation Table), Git и Cassandra (база данных NoSQL). Так что именно определяет такое понятие, как «файловая система»?

Основы файловой системы

Ядро Linux имеет определенные требования к сущности, которая может считаться файловой системой. Она должна реализовывать методы open() , read() и write() для постоянных объектов, которые имеют имена. С точки зрения объектно-ориентированного программирования, ядро определяет обобщенную файловую систему (generic filesystem) в качестве абстрактного интерфейса, а эти три большие функции считаются «виртуальными» и не имеют конкретного определения. Соответственно, реализация файловой системы по умолчанию называется виртуальной файловой системой (VFS).


Если мы можем открывать, читать и записывать в сущность, то эта сущность считается файлом, как мы видим из примера в консоли сверху.
Феномен VFS лишь подчеркивает наблюдение, характерное для Unix-подобных систем, которое гласит, что «всё является файлом». Подумайте, насколько странно, что тот маленький пример сверху с /dev/console показывает, как на самом деле работает консоль. На картинке изображена интерактивная Bash сессия. Отправка строки в консоль (virtual console device) отображает ее на виртуальном экране. VFS имеет другие, еще более странные свойства. Например, она дает возможность осуществлять поиск по ним.

Знакомые нам системы, такие как ext4, NFS и /proc имеют три важные функции в структуре данных С, которая называется file_operations. Кроме того, определенные файловые системы расширяют и переопределяют функции VFS привычным объектно-ориентированным способом. Как отмечает Роберт Лав, абстракция VFS позволяет пользователям Linux беспечно копировать файлы в или из сторонних операционных систем или абстрактных сущностей, таких как pipes, не беспокоясь об их внутреннем формате данных. Со стороны пользователя (userspace) с помощью системного вызова процесс может копировать из файла в структуры данных ядра с помощью метода read() одной файловой системы, а затем использовать метод write() другой файловой системы для вывода данных.

Определения функций, которые принадлежат к базовым типам VFS, находятся в файлах fs/*.c исходного кода ядра, в то время как подкаталоги fs/ содержат определенные файловые системы. В ядре также содержатся сущности, такие как cgroups , /dev и tmpfs , которые требуются в процессе загрузки и поэтому определяются в подкаталоге ядра init/ . Заметьте, что cgroups , /dev и tmpfs не вызывают «большую тройку» функций file_operations , а напрямую читают и пишут в память.
На приведенной ниже диаграмме показано, как userspace обращается к различным типам файловых систем, обычно монтируемых в системах Linux. Не показаны такие конструкции как pipes , dmesg и POSIX clocks , которые также реализуют структуру file_operations , доступ к которым проходит через слой VFS.


VFS — это «слой оболочки» между системными вызовами и реализациями определенных file_operations , таких как ext4 и procfs . Функции file_operations могут взаимодействовать либо с драйверами устройств, либо с устройствами доступа к памяти. tmpfs , devtmpfs и cgroups не используют file_operations , а напрямую обращаются к памяти.
Существование VFS обеспечивает возможность переиспользовать код, так как основные методы, связанные с файловыми системами, не должны быть повторно реализованы каждым типом файловой системы. Переиспользование кода – широкоприменяемая практика программных инженеров! Однако, если повторно используемый код содержит серьезные ошибки, от них страдают все реализации, которые наследуют общие методы.

/tmp: Простая подсказка

Простой способ обнаружить, что VFS присутствуют в системе – это ввести mount | grep -v sd | grep -v :/ , что покажет все смонтированные ( mounted ) файловые системы, которые не являются резидентами на диске и не NFS, что справедливо на большинстве компьютеров. Одним из перечисленных маунтов ( mounts ) VFS, несомненно, будет /tmp , верно?


Все знают, что хранение /tmp на физическом носителе – безумие! Источник.

Почему нежелательно хранить /tmp на физическом носителе? Потому что файлы в /tmp являются временными, а устройства хранения медленнее, чем память, где создается tmpfs. Более того, физические носители более подвержены износу при перезаписи, чем память. Наконец, файлы в /tmp могут содержать конфиденциальную информацию, поэтому их исчезновение при каждой перезагрузке является неотъемлемой функцией.

Помимо /tmp , VFS (виртуальные файловые системы), которые наиболее знакомы пользователям Linux – это /proc и /sys . ( /dev располагается в общей памяти и не имеет file_operations ). Почему именно эти два компонента? Давайте разберемся в этом вопросе.

procfs создает снимок мгновенного состояния ядра и процессов, которые он контролирует для userspace . В /proc ядро выводит информацию о том, какими средствами оно располагает, например, прерывания, виртуальная память и планировщик. Кроме того, /proc/sys – это место, где параметры, настраиваемые с помощью команды sysctl , доступны для userspace . Статус и статистика отдельных процессов выводится в каталогах /proc/ .


Здесь /proc/meminfo — это пустой файл, который тем не менее содержит ценную информацию.

Поведение /proc файлов показывает, какими непохожими могут быть дисковые файловые системы VFS. С одной стороны, /proc/meminfo содержат информацию, которую можно посмотреть командой free . С другой же, там пусто! Как так получается? Ситуация напоминает знаменитую статью под названием «Существует ли луна, когда на нее никто не смотрит? Реальность и квантовая теория», написанную профессором физики Корнельского университета Дэвидом Мермином в 1985 году. Дело в том, что ядро собирает статистику памяти, когда происходит запрос к /proc , и на самом деле в файлах /proc ничего нет, когда никто туда не смотрит. Как сказал Мермин, «Фундаментальная квантовая доктрина гласит, что измерение, как правило, не выявляет ранее существовавшего значения измеряемого свойства.» (А над вопросом про луну подумайте в качестве домашнего задания!)
Кажущаяся пустота procfs имеет смысл, поскольку располагающаяся там информация динамична. Немного другая ситуация с sysfs . Давайте сравним, сколько файлов размером не менее одного байта есть в /proc и в /sys .


Procfs имеет один файл, а именно экспортированную конфигурацию ядра, которая является исключением, поскольку ее нужно генерировать только один раз за загрузку. С другой стороны, в /sys лежит множество более объемных файлов, многие из которых занимают целую страницу памяти. Обычно файлы sysfs содержат ровно одно число или строку, в отличие от таблиц информации, получаемой при чтении таких файлов, как /proc/meminfo .

Цель sysfs – предоставить свойства доступные для чтения и записи того, что ядро называет «kobjects» в userspace. Единственная цель kobjects – это подсчет ссылок: когда удаляется последняя ссылка на kobject, система восстановит ресурсы, связанные с ним. Тем не менее, /sys составляет большую часть знаменитого «stable ABI для userspace» ядра, которое никто никогда, ни при каких обстоятельствах не может «сломать». Это не означает, что файлы в sysfs статичны, что противоречило бы подсчету ссылок на нестабильные объекты.
Стабильный двоичный интерфейс приложений ядра (kernel's stable ABI) ограничивает то, что может появиться в /sys , а не то, что на самом деле присутствует в данный конкретный момент. Листинг разрешений на файлы в sysfs обеспечивает понимание того, как конфигурируемые параметры устройств, модулей, файловых систем и т.д. могут быть настроены или прочитаны. Делаем логический вывод, что procfs также является частью stable ABI ядра, хотя это не указано явно в документации.


Файлы в sysfs описывают одно конкретное свойство для каждой сущности и могут быть читаемыми, перезаписываемыми или и то и другое сразу. «0» в файле говорит о том, что SSD не может быть удален.

Вторую часть перевода начнем с того, как наблюдать за VFS с помощью инструментов eBPF и bcc, а сейчас ждем ваши комментарии и традиционно приглашаем на открытый вебинар, который уже 9 апреля проведет наш преподаватель — Владимир Дроздецкий.

sysfs – виртуальная файловая система операционной системы Linux, которая экспортирует в пространство пользователя через виртуальные файлы информацию о различных подсистемах ядра, подключенных устройствах и соответствующих им драйверах. В дополнение к экспорту информации о различных устройствах и подсистемах виртуальные файлы используются для их конфигурации.

sysfs обеспечивает похожую функциональность, что и sysctl в системах типа BSD. Различие состоит в том, что sysfs - виртуальная файловая система, а sysctl является механизмом встроенным в ядро.

Содержание

История

sysfs - файловая система в оперативной памяти, разработанная Патриком Мошелом, первоначально основанная на ramfs. sysfs первоначально назывался ddfs (Device Driver Filesystem) и была написана для отладки новой модели драйверов. Механизм использовал procfs для экспорта информации из дерева устройств, но под строгими указаниями Линуса Торвальда, был преобразован под использование новой файловой системы основанной на ramfs.

К тому времени новая модель драйверов была объединена в версии ядра 2.5.1 и получила название driverfs, которое лучше отражало ее функциональность. В течение следующего года разработки версии 2.5, инфраструктурные возможности модели driverfs стали казаться полезными для других подсистем. Для центрального управления объектами был разработан механизм kobjects, а driverfs преобразовался в sysfs.

Монтирование sysfs

sysfs монтируется как любая другая файловая система в оперативной памяти:

Также, sysfs может быть смонтирована автоматически при загрузке, используя файл /etc/fstab . Большинство дистрибьютов, поддерживающих ядро версии 2.6, имеют записи для sysfs в /etc/fstab .

Нужно иметь ввиду, что sysfs монтируется в директорию /sys по-умолчанию.

Навигация в sysfs

Поскольку sysfs это просто набор директорий, файлов и символических ссылок, она легко управляется с помощью обычных утилит оболочки (рекомендуется использовать tree(1)).

block

Директория block содержит поддиректории для каждого блока устройства, которое было обнаружено в системе. В директории каждого блока устройства находятся атрибуты, описывающие множество параметров, включая размер устройства и соответствующий ему номер dev_t. Там же находится символическая ссылка, которой сопоставляется соответствующее устройство из физического дерева устройств. Так же, существует директория представляющая интерфейс планировщика ввода/вывода. Этот интерфейс обеспечивает статистическими данными о очереди запросов устройств и некоторые перестраиваемые функции, которые пользователь или администратор могут использовать для оптимизации производительности. Каждый раздел каждого блока устройства представлен как поддиректория блока устройства. Атрибуты в этих директориях только для чтения.

Директория bus содержит поддиректории для каждого типа физической шины, которые поддерживают регистрацию в ядре (либо статически скомпилированы, либо загружаются через модуль).

Каждый тип шины представлен двумя поддиректориями: devices и drivers . Директория devices содержит список устройств, обнаруженных на этом типе шины во всей системе. В списке состоит из символических ссылок, которым соответствуют устройства из физического дерева устройств.

class

devices

firmware

Директория firmware содержит интерфейсы для просмотра и управления определенными объектами прошивки и их атрибутами. Прошивка, в этом случае, ссылается на платформо-ориентированный код, который исполняется при запуске системы. Каждая директория содержит множество объектов и атрибутов специфичных для прошивки.

module

Директория module содержит поддиректории для каждого модуля загруженного в ядро. Имя каждой директории - объединение имени файла объекта модуля и внутреннего имени модуля. Каждый модуль представлен здесь, независимо от того как подсистема зарегистрировала его и присущие ему объекты. Ядро имеет глобальное пространство имен для всех модулей.

Внутри каждой директории находятся поддиректории, называемые секциями. Поддиректории содержат атрибуты секции модуля, которые используются для отладки. Каждая директория модуля содержит хотя бы один атрибут: refcnt. Этот атрибут показывает текущий показатель счетчика ссылок или число пользователей модуля. Это значение аналогично значению четвертой колонки команды lsmod(8) .

power

Директория power представляет подсистемы, частично использующие питание. Директория содержит два атрибута: disk , который управляет механизмом остановки диска; state , который позволяет процессу ввести состояние низкого энергопотребления.

Интерфейс ядра

Функции 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 существует два основных поля, за валидностью которых и нужно следить:

В случае удаления директории, также удалятся все объекты, принадлежащие данной директории, в том числе и файлы.

При вызове функции изменения имени директории, sysfs выделяет новый объект dentry для kobject и вызывает процедуру koject для изменения имени объекта. Если переименование прошло успешно функция вернет 0. В других случаях, функция возвращает отрицательное значение, соответствующее идентификатору ошибки.

Объекты атрибутов

Объекты атрибутов могут быть переданы через sysfs как обычные файлы, используя struct attribute , с соответствующими методами:

Объявление функции Назначение
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); Удаление символической ссылки

Отношение внутри ядра может быть просто указателем между двумя разными объектами. Если оба объекта представлены в sysfs как директории, тогда символическая ссылка между ними может быть создана для предотвращения возникновения избыточной информации. При создании символической ссылки между двумя объектами первый аргумент функции kobject является объектом откуда идет ссылка, то есть директория, где ссылка была создана. Второй аргумент - директория куда указывает ссылка. Третий - имя ссылки в системе.

Группы атрибутов

Интерфейс группы атрибутов это простой интерфейс для добавления и удаления атрибутов за один вызов. Работа с группой атрибутов обеспечивается 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); Удаление бинарного файла

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

В этом блоге публикуются заметки и решения, найденные в процессе работы, освоения и жизни в дистрибутиве Debian GNU/Linux.

Вглубь синтетических джунглей файловой системы sysfs в Linux

Файловая система /sys в Linux отличается от /proc тем, что предоставляет детализированную информацию о работе ядра пользователю (например, параметры устройств и загруженных модулей). Информация строго организована и обычно форматируются простом ASCII тексте, что делает её очень доступной для пользователей и приложений. Так что можно занять шаловливые ручонки чем-нибудь полезным, вроде дёргания разных крутилок в /sys и подсматриванием в системные переменные. Далее - немного подробностей о синтетических джунглях файловой системы /sys .


Зачем нужна /sys, когда есть /proc?
Основной лейтмотив создания /sys было навести некоторый порядок в том бардаке, который являет из себя /proc и выделить информацию о структурах ядра в отдельную директорию.

Sysfs это файловая система, находящаяся в памяти (in-memory), основана первоначально на Ramfs, которая в свою очередь была написана во время перехода на ядро 2.4.0. Как говорит один из авторов [1], ``это было упражнение в элегантности, имевшее целью показать, насколько легко написать простую файловую систему, если использовать новый на тот момент слой VFS''. Из-за простоты и использования VFS, это дало здоровую основу для создания других in-memory файловых систем.

При этом sysfs может быть смонтирована, как и любая другая файловая система из пространства пользователя. Большинство дистрибутивов делают это автоматически при старте системы, добавляя соотвутствующую строчку в /etc/fstab.


Внутри /sys/block
Каталог /sys/ block содержит подкаталоги для каждого блочного устройства, которое было обнаружено в системе. Там хранятся параметры, которые описывают такие свойства блочных устройств, как размер устройства, его партиции, планировщик ввода-вывода и другие.

Зайдя туда, мы обнаруживаем кучу блочных устройств, среди которых можно найти рабочий винчестер, подключённые флешки и внешние жёсткие диски. Вот что автор этих строк нашёл про свой жёсткий диск, на котором установлен евонный Дебиан:

Отсюда мы узнаём, например, что диск /dev/hda разбит на две партиции, hda1 и hda2 , размеры которых хранятся в size , что можно достучаться до планировщика I/O в queue и собрать немножко статистики по работе жёсткого диска в stat . Заглянем туда в поисках приключений и чего-нибудь неизведанного.

Статистика ввода-вывода
Интерфейс /sys/block/sdX/stat даёт некоторые статистические данные о производительности ввода-вывода ядра. Эти данные пользователь или администратор может использовать для оптимизации производительности, если знает, что они значат.

Например, если дать команду:

Мы увидим что-то типа:

186908 41568 6033917 2408504 91198 509600 4882200 9406764 0 1161304 11848624

Эти сакрально-литургические знаки означают следующее:

Поле 1 -- полное число запросов на чтение, выполненных успешно.

Поле 2 -- число объединённых запросов на чтение. Запросы на чтение и запись, примыкающие друг к другу, могут быть объединены для повышения эффективности. Таким образом, два 4K считывания может стать одним 8K считыванием перед тем, как в конечном итоге быть переданы диску. Поэтому запрос будет считаться одним, и это поле позволяет вам узнать, как часто это было сделано.

Поле 3 -- число считанных секторов, чтение которых прошло успешно.

Поле 4 -- миллисекунд, потраченных на чтение.

Поле 5 -- число запросов на запись, выполенных успешно.

Поле 6 -- число объединённых запросов на запись. Запросы на чтение и запись, примыкающие друг к другу, могут быть объединены для повышения эффективности. Таким образом, два 4K считывания может стать одним 8K считыванием перед тем, как в конечном итоге быть переданы диску. Поэтому запрос будет считаться одним, и это поле позволяет вам узнать, как часто это было сделано.

Поле 7 -- число секторов, записанных успешно.

Поле 8 -- миллисекунды, потраченные на запись .

Поле 9 -- число запросов ввода-вывода, активных в данный момент. Единственное поле, которое должно стремиться к нулю .

Поле 10 -- миллисекунд, потраченных на выполнение запросов ввода-вывода.

Поле 11 -- взвешенное количество миллисекунд, потраченных на ввод-вывод . Может использоваться как простая мера производительности ввода-вывода.

Смена планировщика ввода-вывода на лету
Как нам намекает документация, планировщик ввода-вывода может быть изменён в любое время на лету, хотя может быть небольшая задержка из-за того, что все запросы предыдущего планировщика должны быть обработаны прежде, чем запустится новый. Чтобы узнать, какой планировщик стоит сейчас, даём команду:

Заменяя sdX на интересующее нас устройство. Текущий планировщик отмечен в квадратных скобках:
  • noop часто наилучший выбор для файловых систем в памяти (например ramdisk) и других устройств без механических частей (флешек), где попытки оптимизировать ввод-вывод приводят лишь к напрасной трате ресурсов.
  • as ( anticipatory ) по воплощённым в нём идеях схож с deadline , но более навороченный и пытается оптимизировать ввод-вывод с упреждением. Удалён из ядер начиная с 2.6.33.
  • deadline лёгкий планировщик, который пытается установить жёсткий предел на задержки ввода-вывода.
  • cfq поддерживает честное распределение ввода-вывода между процессами, используя концепцию очередей (queue) для каждого процесса. CFQ разедляет синхронные и асинхронные операции ввода-вывода, отдавая предпочтение синхронным операциям. Грубо говоря, CFQ не допускает ситуации, когда один процесс начнёт создавать много операций ввода-вывода, другие процессы могут ``голодать''. Имеет несколько параметров настройки.

Сменить планировщик можно на лету:

После этого планировщик для данного диска будет изменён.



И другие каталоги.
Содержимое других каталогов будет интереснее разработчикам, а не пользователям, и может сильно меняться от версии ядра Linux.

Например, автор этих строк нашёл:

показания температуры на процессоре в ноутбуке. Исключений два - platform devices и system devices.

Platform devices это периферия (подключаемые устройства), присущие конкретной платформе (порты ввода-вывода, legacy-устройства типа последовательного контроллера или контроллера дискет [floppy controller]).

System devices это устройства, интергрированные в платформу, например аппаратные регистры для доступа к конфигурированию, которые не имеют возможностей обмениваться данными. Обычно для них нет драйверов (процессор, таймеры и другое).

/sys/firmware
Cодержит интерфейсы для просмотра и манипулирования firmware-специфичными объектами и их параметрами. Как правило, это платформо-зависимый код, который выполняется в системе при включении, например BIOS.

/sys/module
Cодержит подкаталоги для каждого загруженного модуля ядра. Имя каталога отражает имя модуля. Ядро имеет глобальное пространство имён для всех модулей. Подкаталоги содержат параметры, специфичные для каждого загруженного модуля. Эта информация используется для отладки и простым смертным не будет интересна.

/sys/power
Это скорее заделка на будущее. Может содержать название состояния, которое позволит процессу переходить в режим пониженного энергопотребления.
В зависимости от версии ядра, в /sys могут появляться и другие каталоги.


Ссылки
Есть любопытный документец [1] The sysfs Filesystem, OLS'05 на 14 страниц, написанная тем водянистым и пустозвонным стилем, коий так не переваривает автор этих строк. Документация к ядру тоже не особенно жаждет подробно рассказать о том, что означают все эти переменные и отгораживается вот этим:

Читайте также: