?

Log in

No account? Create an account
 

linux: детский вопрос про дерево каталогов и файловые системы - No Xians Here

About linux: детский вопрос про дерево каталогов и файловые системы

Previous Entry linux: детский вопрос про дерево каталогов и файловые системы 8 фев, 2017 @ 20:39 Next Entry
В линуксе есть папки, откуда мы только запускаем код на исполнение и крайне редко (при апгрейде системы, например, или при установке нового софта) что-то пишем, а то и вовсе никогда не трогаем. Во встроенных системах, ради экономии, это хозяйство заворачивают в romfs и держат на флешке, без шаманизма доступной только в read-only режиме. Но при этом в системе есть так же такие каталоги, которые требуется модифицировать, перезаписывать, создавать в них новые записи и т.п (каталоги /root, /etc, /var, /mnt, /home и т.п.). Т.е. их имеет смысл хранить в той же флешке, но уже в другом разделе, монтируемом в режиме read-write (например, файловая система jffs). Ещё я видел, что делают так: хранят систему в сжатом виде во флешке, а при запуске распаковывают её в ram-диск. Т.е. изменять можно, но изменения не сохраняются при перезагрузке. В такой форме логичнее всего держать (если уж держать) только какие-то временные или вообще виртуальные каталоги, типа /tmp или /dev.

Интересно, существует ли элегантный способ, как в одном дереве каталогов незаметно для пользователя объеденить romfs, jffs и tmpfs. Чтобы получилось нечто такое:
/bin
/sbin
/sys
и прочие подобные каталоги, где системные бинарники и всякие вещи, которые трогать без нужды не следует, лежит в romfs (и НЕ копируются в ram при запуске - ибо нет такой роскоши, как нескончаемые гигабайты быстрой оперативки, но зато есть XIP, поэтому запуск программ оттуда не жрёт оперативку для загрузки кода);
/home
/etc
/root
/mnt
и подобные вещи, где вы мы хотим хранить сохраняемые изменения (и, возможно, код тоже), лежит в jffs (из которой XIP уже не работает, ибо файлы могут быть фрагментированы и физически расположены в беспорядке);
а всё мимолётное-временное, существующее только пока система включена, пусть лежит в воображаемом разделе внутри ram.

В силу врождённого скудоумия, сам я не могу придумать, как такое сделать - ведь чтобы операционке понять, что у неё есть какие-то разные разделы на, возможно, разных носителях, ей нужно сначала прочитать файл /etc/fstab, а если он лежит на каком-то разделе, который мы ещё не подмонтировали, то как его вообще увидеть? Т.е. чтобы подмонтировать раздел, в котором лежит /etc, мы сначала должны прочитать раздел, в котором лежит /etc. Этот парадокс вообще разрешим или я зря надеюсь?
Оставить комментарий
[User Picture Icon]
From:Chairman Meow [antv.org]
Date:Февраль, 8, 2017 18:14 (UTC)

Даже несколько способов

(Link)
В линуксе есть даже несколько способов (при наличии последнего ядра): bind mount, union mount и overlay mount.

Union: lwn.net/Articles/312641/
Bind: backdrift.org/how-to-use-bind-mounts-in-linux
Overlay: wiki.archlinux.org/index.php/Overlay_filesystem - это скорей всего самый простой вариант
[User Picture Icon]
From:kincajou
Date:Февраль, 8, 2017 18:33 (UTC)
(Link)
вот что-то вроде union и нужно. Чтобы оно уже работало, когда запущено только ядро с драйверами и всё, больше ничего ещё не загружено.
[User Picture Icon]
From:Chairman Meow [antv.org]
Date:Февраль, 8, 2017 18:51 (UTC)
(Link)
А это обычно делается через initrd: www.tldp.org/LDP/Linux-Filesystem-Hierarchy/html/initrd.html

Т.е. ядро монтирует initrd с squashfs в режиме read-only и запускает /linuxrc - а дальше скрипт (ну или бинарник) монтирует все остальное.

Ну или ядру можно передать путь к root fs с помощью параметра root= и потом оно все остальное монтирует - там куча аргументов www.kernel.org/doc/Documentation/admin-guide/kernel-parameters.txt , но по идее ядру можно сказать что-то типа root=UUID=ABCDEF... и дальше ядро само просканирует все носители которые оно распознало и монтирует файлсистему с нужным UUID
[User Picture Icon]
From:kincajou
Date:Февраль, 8, 2017 19:06 (UTC)
(Link)
тут будет u-boot
он тоже может передавать параметры ядру
From:exzerodivide
Date:Февраль, 8, 2017 18:37 (UTC)

На самом деле

(Link)
... описана стандартная схема для всяких модемов на линуксе и прочих CPE, включая телефоны.
Выглядит на практике примерно так:
1. Есть N разделов на MTD: раздел 1 - ядро + initramfs, раздел 2...N - все остальное, включая свап.
Загрузка выглядит так (упрощенно): загрузчик, зная разметку MTD, передает управление начальному коду ядра, включая аргументы, указывающие что и откуда грузить.
2. Ядро в процессе загрузки распознает разметку MTD
3. Загрузка завершается распаковкой initramfs в память и запуском init. Все, дальше делаем что хотим.
Минимальное наполнение initramfs очевидно (структура каталогов, бизибокс, стартовые скрипты и так далее). Тут чуть подробнее про механизм https://en.wikipedia.org/wiki/Initramfs

Правильнее даже делать 2 раздела под kernel+initramfs, указывая бутлодырю с какого раздела грузить ядро. При этом перешивка становится более простой и устойчивой + возможность переключиться на работающий раздел при вливании неудачного образа. Хотя может это и избыточно.
[User Picture Icon]
From:kincajou
Date:Февраль, 8, 2017 18:43 (UTC)
(Link)
Загрузка завершается распаковкой initramfs в память
вот от этого я и хочу избавиться. Чип может исполнять код прямо из внешней флешки - XIP это "execute in place". Чтобы оно работало, достаточно передать управление на нужный адрес и всё, дальше дело техники. Естественно, код должен быть вытянут в струнку - вот как он получился при компиляции, так и расположен во флешке, байт-в-байт. Поэтому из сложных ФС так не запустить и нужна загрузка в ОЗУ, а вот romfs, где файлы есть просто бинарные массивы и лежат "друг за другом" (с соответствующей табличкой, которую мы читаем и видим, что где), подходит идеально. Без компрессии и чего-то такого. Идеально подходит для неизменяемого в процессе работы кода (системные бинарники, какие-то утилиты и т.п.)
From:exzerodivide
Date:Февраль, 8, 2017 18:51 (UTC)
(Link)
тогда по идее связка kernel+romfs должна работать ничем не хуже. Хотя я такое на практике не видел (в смысле - применений).
Изменяемые части можно действительно через overlay сделать, или тупо путем монтирования изменяемых fs в соответствующие точки.
[User Picture Icon]
From:kincajou
Date:Февраль, 8, 2017 19:00 (UTC)
(Link)
в эмбеде должно встречаться часто, уж очень удобный способ экономии памяти
From:exzerodivide
Date:Февраль, 8, 2017 19:33 (UTC)
(Link)
Возможно что так и есть. С тем "эмбедом" что я сталкивался (сетевые и околосетевые железяки от кабельных модемов и мелкороутеров asus wl-330 n3g и выше) подход один и тот же: initramfs.
В любом случае выбранный Вами подход выглядит в высшей степени жизнеспособным.
From:ex0_planet
Date:Февраль, 8, 2017 19:01 (UTC)
(Link)
В десктопных livecd это делается на основе union fs, но в ванильном ядре ни одной по-моему так и нету. Конкретно дебианоиды пользуются для этого AUFS, что делают редхатоиды — хз.

Проблема "курицы и яйца" в монтировании решается двухфазным mount'ом: 1) монтирование "критически важных фс"; 2) монтирование всех остальных. При этом тащемта неважно куда именно выносить эти фазы: это может быть либо initrd + основная система, либо две стадии в основном init... Начальные какие-то сведения идут все равно через загрузчик.

[User Picture Icon]
From:kincajou
Date:Февраль, 8, 2017 19:33 (UTC)
(Link)
у меня будет.. х.з. что будет. Самопильный линукс с минимально-достаточной для запуска простейших вещей функциональностью: сеть, usb и т.п. Может быть, удастся запилить Qt (но мне заранее страшно). Маловероятно, что это будет какой-то "стандартный" дистрибутив
From:ex0_planet
Date:Февраль, 8, 2017 19:04 (UTC)
(Link)
А, да. Еще можно сделать маленькую фс, содержащую каталоги etc, var, root и что там тебе еще надо, монтировать ее при загрузке куда-нибудь в /mnt/volatile, а потом bind mount'ами растаскивать по нужным местам.
[User Picture Icon]
From:metaclass
Date:Февраль, 9, 2017 11:04 (UTC)
(Link)
Ты не про overlayfs случаем?
https://wiki.openwrt.org/doc/techref/flash.layout - тут вроде описано, как в openwrt они это делают.
(Оставить комментарий)
Top of Page Разработано LiveJournal.com