Віртуальні файлові системи в Linux: навіщо вони потрібні та як вони працюють? Частина 2

Всім привіт, ділимося з вами другою частиною публікації "Віртуальні файлові системи в Linux: навіщо вони потрібні і як вони працюють?" Першу частину можна прочитати тут. Нагадаємо, дана серія публікацій присвячена запуску нового потоку за курсом. «Адміністратор Linux», Що стартує вже зовсім скоро.

Як спостерігати за VFS за допомогою інструментів eBPF та bcc

Найпростіший спосіб зрозуміти, як ядро ​​оперує файлами sysfs – це подивитися за цим на практиці, а найпростіший спосіб спостерігати за ARM64 – це використовувати eBPF. eBPF (скорочення від Berkeley Packet Filter) складається з віртуальної машини, запущеної в ядрі, яку привілейовані користувачі можуть запитувати (query) з командного рядка. Вихідники ядра повідомляють читачеві, що може зробити ядро; запуск інструментів eBPF у завантаженій системі показує, що насправді робить ядро.

Віртуальні файлові системи в Linux: навіщо вони потрібні та як вони працюють? Частина 2

На щастя, почати використовувати eBPF досить легко за допомогою інструментів ОЦК, які доступні як пакети із загального дистрибутива Linux та детально задокументовані Бернардом Греггом. Інструменти bcc – це скрипти на Python з маленькими вставками коду на С, це означає, що кожен, хто знайомий з обома мовами може легко їх модифікувати. У bcc/tools є 80 Python скриптів, а це означає, що швидше за все розробник або системний адміністратор зможе підібрати собі щось потрібне для вирішення завдання.
Щоб отримати хоча б поверхове уявлення про те, яку роботу виконують VFS у запущеній системі, спробуйте vfscount або vfsstat. Це покаже, скажімо, що десятки викликів vfs_open() і його друзів відбуваються буквально кожну секунду.

Віртуальні файлові системи в Linux: навіщо вони потрібні та як вони працюють? Частина 2

vfsstat.py – це скрипт на Python, із вставками C коду, який просто вважає виклики функцій VFS.

Наведемо більш очевидний приклад і подивимося, що буває, коли ми вставляємо USB-флеш накопичувач у комп'ютер і його виявляє система.

Віртуальні файлові системи в Linux: навіщо вони потрібні та як вони працюють? Частина 2

За допомогою eBPF можна подивитися, що відбувається у /sys, коли вставлено флеш-накопичувач USB. Тут показаний простий та складний приклад.

У прикладі, показаному зверху, bcc інструмент trace.py виводить повідомлення, коли запускається команда sysfs_create_files(). Ми бачимо, що sysfs_create_files() був запущений за допомогою kworker потоку у відповідь те що, що флешка було вставлено, але який файл у своїй створився? Другий приклад показує всю потужність eBPF. Тут trace.py виводить зворотне трасування ядра (kernel backtrace) (опція -K) та ім'я файлу, який був створений sysfs_create_files(). Вставка в одиночних висловлюваннях – це код на С, що включає рядок формату, що легко розпізнається, забезпечуваний Python скриптом, який запускає LLVM just-in-time компілятор. Цей рядок він компілює та виконує у віртуальній машині всередині ядра. Повна сигнатура функції sysfs_create_files () має бути відтворена в другій команді, щоб рядок формату міг посилатися на один із параметрів. Помилки в цьому фрагменті коду С призводять до розпізнаваних помилок C-компілятора. Наприклад, якщо пропущено параметр -l, ви побачите «Failed to compile BPF text.» Розробники, які добре знайомі з С та Python, знайдуть інструменти bcc простими для розширення та зміни.

Коли USB-накопичувач вставлений, зворотне трасування ядра покаже, що PID 7711 це потік kworker, який створив файл «events» в sysfs. Відповідно, виклик з sysfs_remove_files() покаже, що видалення накопичувача призвело до видалення файлу events, що відповідає загальній концепції підрахунку посилань. При цьому перегляд sysfs_create_link () з eBPF під час вставки USB-накопичувача покаже, що створено щонайменше 48 символьних посилань.

Так у чому сенс файлу events? Використання cscope для пошуку __device_add_disk()показує, що вона викликає disk_add_events (), і або "media_change", або "eject_request" можуть бути записані у подій файл. Тут блоковий шар ядра інформує userspace про появу та вилучення «диска». Зверніть увагу, наскільки інформативний цей метод дослідження на прикладі вставки USB-накопичувача в порівнянні зі спробами з'ясувати виключно з вихідних джерел.

Кореневі файлові системи тільки для читання уможливлюють вбудовані пристрої

Звичайно, ніхто не вимикає сервер або свій комп'ютер, витягаючи вилку з розетки. Але чому? А все тому, що змонтовані файлові системи на фізичних пристроях зберігання можуть мати відкладені записи, а структури даних, що записують їх стан, можуть не синхронізуватися із записами в сховищі. Коли це трапляється, власникам системи доводиться чекати наступного завантаження для запуску утиліти fsck filesystem-recovery і, у гіршому випадку, втратити дані.

Тим не менш, всі ми знаємо, що багато IoT пристроїв, а також маршрутизатори, термостати та автомобілі тепер працюють під керуванням Linux. Багато з цих пристроїв практично не мають інтерфейсу користувача, і немає ніякого способу вимкнути їх «чисто». Уявіть собі запуск автомобіля з розрядженою батареєю, коли живлення керуючого пристрою Linux постійно скаче вгору-вниз. Як виходить, що система завантажується без довгого fsckколи двигун нарешті починає працювати? А відповідь проста. Вбудовані пристрої покладаються на кореневу файлову систему тільки для читання (скорочено ro-rootfs (read-only root fileystem)).

ro-rootfs пропонують безліч переваг, які менш очевидні, ніж непідробленість. Одна з переваг полягає в тому, що шкідливе програмне забезпечення не може писати в /usr або /libякщо жоден процес Linux не може туди писати. Інше полягає в тому, що значною мірою незмінна файлова система має вирішальне значення для польової підтримки віддалених пристроїв, оскільки допоміжний персонал користується локальними системами, які номінально ідентичні системам на місцях. Можливо, найважливішою (але й найпідступнішою) перевагою є те, що ro-rootfs змушує розробників вирішувати, які системні об'єкти будуть незмінними, ще на етапі проектування системи. Робота з ro-rootfs може бути незручною та болісною, як це часто буває зі змінними const у мовах програмування, але їх переваги легко окупають додаткові накладні витрати.

Створення rootfs тільки для читання вимагає деяких додаткових зусиль для розробників систем, що вбудовуються, і саме тут на сцену виходить VFS. Linux вимагає, щоб файли в /var були доступні для запису, і, крім того, багато популярних програм, які запускають вбудовані системи, намагатимуться створити конфігураційні dot-files в $HOME. Одним із рішень для конфігураційних файлів у домашньому каталозі зазвичай є їх попередня генерація та складання в rootfs. Для /var один із можливих підходів — це змонтувати його в окремий розділ, доступний для запису, тоді як сам / монтується лише для читання. Іншою популярною альтернативою є використання маунтів, що зв'язуються або накладаються (bind or overlay mounts).

Маунти, що зв'язуються та накладаються, використання їх контейнерами

Виконання команди man mount - найкращий спосіб дізнатися про маунти, що зв'язуються і накладаються, які дають розробникам і системним адміністраторам можливість створювати файлову систему по одному шляху, а потім надавати її додаткам в іншому. Для вбудованих систем це означає можливість зберігати файли в /var на флеш-накопичувачі, доступному тільки для читання, але монтування шляху, що накладається або зв'язується з tmpfs в /var при завантаженні дозволить програмам записувати туди нотатки (scrawl). При наступному включенні зміни до /var будуть втрачені. Накладене монтування створює об'єднання між tmpfs та нижчележачою файловою системою і дозволяє робити нібито зміни існуючих файлів у ro-tootf тоді як монтування, що зв'язується, може зробити нові порожні tmpfs папки видимими як доступні для запису в ro-rootfs шляхах. В той час як overlayfs це правильний (proper) тип файлової системи, що зв'язується монтування реалізовано в просторі імен VFS.

Грунтуючись на описі монтування, що накладається і зв'язується, ніхто не дивується що Linux контейнери активно їх використовують. Давайте поспостерігаємо, що відбувається, коли ми використовуємо systemd-nspawn для запуску контейнера, використовуючи інструмент mountsnoop від bcc.

виклик system-nspawn запускає контейнер під час роботи mountsnoop.py.

Подивимося, що вийшло:

запуск mountsnoop під час «завантаження» контейнера показує, що середовище виконання контейнера сильно залежить від монтування, що зв'язується (Відображається тільки початок довгого виведення).

Тут systemd-nspawn надає вибрані файли в procfs и sysfs хоста у контейнер як шляхи у його rootfs. Крім MS_BIND прапора, який встановлює зв'язуюче монтування, деякі інші прапори в системі, що монтується, визначають взаємозв'язок між змінами в просторі імен хоста і контейнера. Наприклад, монтування, що зв'язується, може або пропускати зміни в /proc и /sys у контейнер, або приховувати їх залежно від дзвінка.

Висновок

Розуміння внутрішнього пристрою Linux може здаватися нездійсненним завданням, оскільки саме ядро ​​містить гігантську кількість коду, залишаючи осторонь програми користувальницького простору Linux та інтерфейси системних викликів у бібліотеках мовою C, таких як glibc. Один із способів досягти прогресу — прочитати вихідний код однієї підсистеми ядра з акцентом на розуміння системних викликів і заголовків, звернених до простору користувача, а також основних внутрішніх інтерфейсів ядра, наприклад, таблиця file_operations. Файлові операції забезпечують принцип "все є файлом", тому керування ними особливо приємно. Вихідні файли ядра мовою C у каталозі верхнього рівня fs/ представляють реалізацію віртуальних файлових систем, які є шаром оболонки, що забезпечує широку та просту сумісність популярних файлових систем та пристроїв зберігання. Монтування зі зв'язуванням і накладенням через простори імен Linux - це диво VFS, яке уможливлює створення контейнерів і кореневих файлових систем тільки для читання. У поєднанні з вивченням вихідного коду, засіб ядра eBPF та його інтерфейс bcc
роблять дослідження ядра простіше, ніж будь-коли.

Друзі, напишіть, чи була ця стаття корисною для вас? Можливо у вас є якісь коментарі чи зауваження? А тих, кому цікавий курс «Адміністратор Linux», запрошуємо на день відкритих дверей, який відбудеться 18 квітня

Перша частина.

Джерело: habr.com

Додати коментар або відгук