Здравейте всички, споделяме с вас втората част от публикацията „Виртуални файлови системи в Linux: защо са необходими и как работят?“ Можете да прочетете първата част
Как да наблюдавате VFS с помощта на eBPF и bcc инструменти
Най-лесният начин да разберете как ядрото работи с файлове sysfs
е да го видите на практика, а най-лесният начин да гледате ARM64 е да използвате eBPF. eBPF (съкратено от Berkeley Packet Filter) се състои от работеща виртуална машина query
) от командния ред. Източниците на ядрото казват на читателя какво може да направи ядрото; стартирането на инструментите eBPF на заредена система показва какво всъщност прави ядрото.
За щастие, да започнете да използвате eBPF е доста лесно с помощта на инструменти bcc
са Python скриптове с малки вмъквания на C код, което означава, че всеки, запознат с двата езика, може лесно да ги модифицира. IN bcc/tools
Има 80 Python скрипта, което означава, че най-вероятно разработчик или системен администратор ще може да избере нещо подходящо за решаване на проблема.
За да получите поне повърхностна представа каква работа вършат VFS на работеща система, опитайте vfscount
или vfsstat
. Това ще покаже, да кажем, че десетки обаждания vfs_open()
а „приятелите му“ се случват буквално всяка секунда.
vfsstat.py
е скрипт на Python с вмъквания на C код, който просто брои извикванията на VFS функция.
Нека дадем по-тривиален пример и да видим какво се случва, когато поставим USB флашка в компютъра и системата го засече.
С помощта на eBPF можете да видите какво се случва в
/sys
когато е поставено USB флаш устройство. Тук е показан прост и сложен пример.
В примера, показан по-горе, bcc
инструмент sysfs_create_files()
. Виждаме това sysfs_create_files()
беше стартиран с помощта на kworker
поток в отговор на факта, че флаш устройството е поставено, но какъв файл е създаден? Вторият пример показва силата на eBPF. Тук trace.py
Отпечатва обратно проследяване на ядрото (опция -K) и името на файла, който е създаден sysfs_create_files()
. Вмъкването на единичен израз е C код, който включва лесно разпознаваем форматиращ низ, предоставен от скрипта на Python, който изпълнява LLVM компилатор точно навреме. Той компилира този ред и го изпълнява във виртуална машина в ядрото. Пълен функционален подпис sysfs_create_files ()
трябва да се възпроизведе във втората команда, така че форматиращият низ да може да препраща към един от параметрите. Грешките в тази част от C кода водят до разпознаваеми грешки от C компилатора. Например, ако параметърът -l е пропуснат, ще видите „Неуспешно компилиране на BPF текст“. Разработчиците, които са запознати със C и Python, ще намерят инструментите bcc
лесен за разширяване и промяна.
Когато USB устройството бъде поставено, обратното проследяване на ядрото ще покаже, че PID 7711 е нишка kworker
който създаде файла «events»
в sysfs
. Съответно обаждането от sysfs_remove_files()
ще покаже, че премахването на устройството е довело до изтриването на файла events
, което съответства на общата концепция за броене на справки. В същото време, гледане sysfs_create_link ()
с eBPF, докато поставяте USB устройството, ще покаже, че са създадени поне 48 символни връзки.
И така, какъв е смисълът на файла със събития? Използване disk_add_events ()
, и едно от двете "media_change"
Или "eject_request"
могат да бъдат записани във файл на събитието. Тук блоковият слой на ядрото информира потребителското пространство, че "диск" се е появил и е изваден. Обърнете внимание колко информативен е този метод на изследване чрез поставяне на USB устройство в сравнение с опитите да разберете как работят нещата само от източника.
Основните файлови системи само за четене позволяват вградени устройства
Разбира се, никой не изключва сървъра или компютъра си, като издърпа щепсела от контакта. Но защо? Това е така, защото монтираните файлови системи на физически устройства за съхранение може да имат закъснели записи и структурите от данни, които записват тяхното състояние, може да не са синхронизирани със записи в паметта. Когато това се случи, собствениците на системата трябва да изчакат до следващото зареждане, за да стартират помощната програма. fsck filesystem-recovery
и в най-лошия случай загуба на данни.
Въпреки това, всички знаем, че много IoT устройства, както и рутери, термостати и автомобили, сега работят с Linux. Много от тези устройства имат малък или никакъв потребителски интерфейс и няма начин да ги изключите "чисто". Представете си да запалите кола с изтощен акумулатор, когато захранването на контролния блок е изчерпано fsck
кога двигателя най-накрая започва да работи? А отговорът е прост. Вградените устройства разчитат на основната файлова система ro-rootfs
(основна файлова система само за четене)).
ro-rootfs
предлагат много предимства, които са по-малко очевидни от автентичността. Едно предимство е, че зловреден софтуер не може да пише /usr
или /lib
, ако никой Linux процес не може да пише там. Друго е, че до голяма степен неизменна файлова система е от решаващо значение за поддръжката на място на отдалечени устройства, тъй като персоналът по поддръжката разчита на локални системи, които са номинално идентични на системите на място. Може би най-важното (но и най-коварното) предимство е, че ro-rootfs принуждава разработчиците да решат кои системни обекти ще бъдат неизменни на етапа на проектиране на системата. Работата с ro-rootfs може да бъде неудобна и болезнена, тъй като променливите const често са в езиците за програмиране, но техните предимства лесно оправдават допълнителните разходи.
създаване rootfs
Само за четене изисква допълнителни усилия за разработчиците на вградени системи и тук се появява VFS. Linux изисква файловете да са вътре /var
могат да се записват и в допълнение много популярни приложения, които изпълняват вградени системи, ще се опитат да създадат конфигурация dot-files
в $HOME
. Едно решение за конфигурационните файлове в началната директория обикновено е предварителното им генериране и вграждане rootfs
. За /var
Един възможен подход е да го монтирате на отделен дял с възможност за запис, докато /
монтиран само за четене. Друга популярна алтернатива е използването на скоби за свързване или наслагване.
Свързващи се и подреждащи се стойки, използването им от контейнери
Изпълнение на команда man mount
е най-добрият начин да научите за монтиране с възможност за обвързване и наслагване, което дава възможност на разработчиците и системните администратори да създават файлова система в една пътека и след това да я излагат на приложения в друга. За вградените системи това означава възможност за съхраняване на файлове /var
на флаш устройство само за четене, но път за наслагване или свързване от tmpfs
в /var
при зареждане ще позволи на приложенията да пишат бележки там (драскане). Следващият път, когато включите промените в /var
ще бъдат загубени. Монтажът за наслагване създава съюз между tmpfs
и основната файлова система и ви позволява да правите привидни промени в съществуващите файлове в ro-tootf
като има предвид, че подвързваемото монтиране може да направи новите празни tmpfs
папки, видими като в тях могат да се записват ro-rootfs
начини. Докато overlayfs
това е правилното (proper
) тип файлова система, монтиране с възможност за свързване е внедрено в
Въз основа на описанието на наслагването и монтажа за свързване, никой не е изненадан от това 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 администратор, са поканени
Източник: www.habr.com