Усім прывітанне, дзелімся з вамі другой часткай публікацыі "Віртуальныя файлавыя сістэмы ў Linux: навошта яны патрэбныя і як яны працуюць?" Першую частку можна прачытаць
Як назіраць за VFS з дапамогай інструментаў eBPF і bcc
Самы просты спосаб зразумець, як ядро аперуе файламі sysfs
- гэта паглядзець за гэтым на практыцы, а самы просты спосаб паназіраць за ARM64 - гэта выкарыстоўваць eBPF. eBPF (скарачэнне ад Berkeley Packet Filter) складаецца з віртуальнай машыны, запушчанай у query
) з каманднага радка. Зыходнікі ядра паведамляюць чытачу, што можа зрабіць ядро; запуск прылад eBPF у загружанай сістэме паказвае, што насамрэч робіць ядро.
На шчасце, пачаць выкарыстоўваць eBPF дастаткова лёгка з дапамогай інструментаў bcc
- гэта скрыпты на Python з маленькімі ўстаўкамі кода на З, гэта азначае, што кожны, хто знаёмы з абедзвюма мовамі можа з лёгкасцю іх мадыфікаваць. У bcc/tools
ёсць 80 Python скрыптоў, а гэта значыць, што хутчэй за ўсё распрацоўшчык або сістэмны адміністратар зможа падабраць сабе што-небудзь прыдатнае для рашэння задачы.
Каб атрымаць хаця б павярхоўнае ўяўленне аб тым, якую працу выконваюць VFS у запушчанай сістэме, паспрабуйце vfscount
або vfsstat
. Гэта пакажа, дапусцім, што дзясяткі выклікаў vfs_open()
і "яго сяброў" адбываюцца літаральна кожную секунду.
vfsstat.py
- гэта скрыпт на Python, з устаўкамі З кода, які проста лічыць выклікі функцый VFS.
Прывядзем больш трывіяльны прыклад і паглядзім, што бывае, калі мы ўстаўляемы USB-флэш назапашвальнік у кампутар і яго выяўляе сістэма.
З дапамогай eBPF можна паглядзець, што адбываецца ў
/sys
, калі ўстаўлены USB-флэш назапашвальнік. Тут паказаны просты і складаны прыклад.
У прыкладзе, паказаным зверху, bcc
інструмент 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? Выкарыстанне disk_add_events ()
, і альбо "media_change"
, Альбо "eject_request"
могуць быць запісаны ў файл падзей. Тут блокавы пласт ядра інфармуе userspace аб з'яўленні і выманні "дыска". Звярніце ўвагу, наколькі інфарматыўны гэты метад даследавання на прыкладзе ўстаўкі USB-назапашвальніка ў параўнанні са спробамі высветліць, як усё працуе, выключна з зыходнікаў.
Каранёвыя файлавыя сістэмы толькі для чытання робяць магчымымі убудаваныя прылады
Вядома, ніхто не выключае сервер ці свой кампутар, выцягваючы відэлец з разеткі. Але чаму? А ўсё таму што змантаваныя файлавыя сістэмы на фізічных прыладах захоўвання могуць мець адкладзеныя запісы, а структуры дадзеных, якія запісваюць іх стан, могуць не сінхранізавацца з запісамі ў сховішча. Калі гэта здараецца, уладальнікам сістэмы даводзіцца чакаць наступнай загрузкі для запуску ўтыліты fsck filesystem-recovery
і, у горшым выпадку, страціць дадзеныя.
Тым не менш, усе мы ведаем, што многія IoT прылады, а таксама маршрутызатары, тэрмастаты і аўтамабілі зараз працуюць пад кіраваннем 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
) тып файлавай сістэмы, злучанае мантаванне рэалізавана ў
Грунтуючыся на апісанні накладваемага і злучанага мантавання, ніхто не дзівіцца што 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", запрашаем на
Крыніца: habr.com