?

Log in

 

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 18:59 (UTC)
(Link)
на кой ляд тогда существует /etc/fstab ?
[User Picture Icon]
From:Chairman Meow [antv.org]
Date:Февраль, 8, 2017 19:20 (UTC)
(Link)
А ядро монтирует только root fs, все остальное монтируется из юзерспейса программами на root fs. fstab при этом в основном для удобства админа, чтобы в скрипте 10 раз не писать "mount /dev/sda1 /mnt/volume1". Теоретически fstab вообще не обязателен, по идее ядро монтирует root fs и запускает с него /sbin/init (или то что указано в аргументе init=...) и все - а сам init может быть даже кастомным бинарником который тупо вызывает man7.org/linux/man-pages/man2/mount.2.html и никаких файлов из /etc вообще не читает.
[User Picture Icon]
From:kincajou
Date:Февраль, 8, 2017 19:28 (UTC)
(Link)
то есть, если ядро монтирует только rootfs, который у нас по условиям задачи должен быть read-only, то только init подскажет ядру о существовании другого раздела, в котором /etc ? А можно ли сделать так, что init ТОЛЬКО подмонтирует этот другой раздел и туда уже передаст управление чему-то типа /etc/init.rd/superduperinitscript, который уже и можно будет потом подкрутить-поднастроить?
[User Picture Icon]
From:Chairman Meow [antv.org]
Date:Февраль, 8, 2017 19:40 (UTC)
(Link)
Вполне себе может - ядро запускает /sbin/init и дальше "умывает руки", все остальные процессы запускаются из init. Сам инит вполне может делать что-то типа:

mount("/dev/sda1","/etc", "ext4", 0, NULL)
execve("/etc/init.d/init_stage2", NULL, NULL)
[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.
В любом случае выбранный Вами подход выглядит в высшей степени жизнеспособным.
[User Picture Icon]
From:kincajou
Date:Февраль, 8, 2017 19:54 (UTC)
(Link)
initramfs всегда можно заюзать, если мой вариант окажется нереализуемым
From:exzerodivide
Date:Февраль, 8, 2017 20:40 (UTC)
(Link)
Погуглил быстро про XIP и линукс - в общем опыт у Вас будет судя по всему увлекательным :-)
Использование XIP налагает кстати ряд ограничений, например невозможность использования MTD для устройства, с которого предполагается XIP, необходимость использования CramFS/Linear CramFS для хранения исполняемых файлов (вопрос с rootfs неочевиден), и так далее.
[User Picture Icon]
From:kincajou
Date:Февраль, 8, 2017 20:48 (UTC)
(Link)
хмм... вот этого я не знал. Значит, так только ядро можно...

но если для хранения исполняемых файлов применять компрессированную ФС, разворачиваемую в RAM, то какой смысл (и каким боком) это XIP?
From:exzerodivide
Date:Февраль, 8, 2017 20:56 (UTC)
(Link)
Если много флэша и мало рама - то почему бы и нет ? Та же MontaVista Linux его активно умеет. А монтависта изначально под ембеддед точилась (погуглите). Тем более что XIP получается более энергоэффективным (мало рама - мало рефреша)
В общем для затравки:
http://elinux.org/Kernel_XIP
http://elinux.org/Application_XIP

http://www.denx.de/wiki/DULG/ConfigureLinuxForXIP
http://vanguardiasur.com.ar/how-to-prepare-and-boot-a-xip-linux-kernel-on-lpc43xx/

Я бы попробовал - проект то фановый.
[User Picture Icon]
From:kincajou
Date:Февраль, 8, 2017 21:08 (UTC)
(Link)
не-не, вопрос в том, как использовать XIP в случае CRAMFS? это же.. взаимоисключающие вещи получаются. И как раз надо МНОГО ram
From:exzerodivide
Date:Февраль, 8, 2017 21:13 (UTC)
(Link)
Зойчем ? https://en.wikipedia.org/wiki/Cramfs
Оно лежит на флэше, даже с прозрачным сжатием. Исполнение прям оттуда.
[User Picture Icon]
From:kincajou
Date:Февраль, 8, 2017 21:25 (UTC)
(Link)
энене. Куда осуществляется разжатие ПЕРЕД исполнением, хм? В мировой эфир? ;) Процессор же не умеет исполнять lzma-сжатый код, ему подавай нативные машинные команды
From:exzerodivide
Date:Февраль, 8, 2017 21:46 (UTC)
(Link)
Ну код биоса же исполняется без рама до момента инициализации памяти. Все на регистрах. А мы чем хуже ? :-)
Если кроме шуток, то:
1. cramfs использует для сжатия gzip, не lzma, причем постранично. То есть: вся фс - не один gzip-поток, а набор потоков, каждый длиной со страницу. То есть - при исполнении в память мы разжимаем по сути всего одну страницу фс.
2. Подробности можно почитать и подсмотерть тут https://lwn.net/Articles/235532/

Edited at 2017-02-08 21:48 (UTC)
[User Picture Icon]
From:kincajou
Date:Февраль, 8, 2017 23:07 (UTC)
(Link)
каким блин способом можно исполнять зазипованный софт, не раззиповывая его куда-то в промежуточное хранилище?
From:exzerodivide
Date:Февраль, 8, 2017 23:37 (UTC)
(Link)
Исполнение в любом случае идет из некого буфера.
А так - раззиповывая, но постранично. Размер страницы в случае крамфс - 4 кб как я понимаю.
В ядерном реадми структура описана кстати http://lxr.linux.no/linux/fs/cramfs/README

Посмотрите на это под другим углом - как исполняется файл, чья часть по воле аллаха улетела в своп ?
Своп можно рассматривать как черный ящик: запросили диапазон адресов - отдал. Как он там их хранит - его дело. Главное - чтобы отдавал.

В любом случае вариантов всего два: либо распаковывать исполняемый код целиком в память и там исполнять, либо эмуляция свопа. Надо исходники на XIP + CramFS внимательно смотреть, как именно там реализовано.
[User Picture Icon]
From:kincajou
Date:Февраль, 9, 2017 00:02 (UTC)
(Link)
Исполнение в любом случае идет из некого буфера.
в случае XIP исполнение идёт "по месту". Именно поэтому это так называется. Например, код лежит в флешке, отображаемой на общее адресное пространство. Ничего никуда копировать не надо, просто инициализируем порт, пишем в микросхему команду перехода в XIP режим, прыгаем на нужный адрес и понеслась! и в некоторых случаях исполнение оттуда несколько медленнее, чем из внутренней флеши, но не фатально. Скажем, есть флешки, поддерживающие DDR, т.е. за оидн такт читается 8 бит - шина в таком режиме работает на частоте не более 80 МГц, т.е. это 80 МБ/с. SDR режим разгоняется до 108 мегагерц, чтение 4 бита на такт, т.е. 54 МБ/с. Это медленнее встроенной флеши, но всё равно вполне терпимо - тем более что кэш работает для этой памяти. В основном, это именно для экономии ОЗУ, чтобы ничего никуда не грузить, именно в этом весь смысл.

Edited at 2017-02-09 00:55 (UTC)
From:exzerodivide
Date:Февраль, 9, 2017 08:51 (UTC)
(Link)
В общем оно там хитрее оказалось устроено. Несмотря на то, что фс со сжатием, xip-файлы помечаются стики-битом, и тогда при сборке образа такие файлы не жмутся. Причем это описано в патче, но не описано в описании фс. Так что интриги нет, расходимся :-)
[User Picture Icon]
From:kincajou
Date:Февраль, 9, 2017 00:06 (UTC)
(Link)
как исполняется файл, чья часть по воле аллаха улетела в своп ?
а вот для этого нужен MMU, чтобы работал полноценный mmap()
From:exzerodivide
Date:Февраль, 9, 2017 08:55 (UTC)
(Link)
Написал, и потом подумал что сначала было бы неплохо уточнить, есть ли у чипа mmu. Это ведь тот самый проц, у которого приключения с dma были ? Или другой ?

Edited at 2017-02-09 08:56 (UTC)
[User Picture Icon]
From:kincajou
Date:Февраль, 9, 2017 17:40 (UTC)
(Link)
другой, но тоже cortex-m, просто постарше - не 3, а 7
[User Picture Icon]
From:kincajou
Date:Февраль, 8, 2017 21:04 (UTC)
(Link)
с другой стороны, XIP подразумевает прозрачное цотображение флэшки на адресное пространство, значит, rootfs можно разместить в "ramfs", которая на самом деле romfs?
From:exzerodivide
Date:Февраль, 8, 2017 21:10 (UTC)
(Link)
По сути так, да.
Ядру на самом деле глубоко фиолетово, где находится инит и корневая фс. Это может быть initrd/initramfs или любая другая fs. Главное - чтобы инит мог быть выполнен ядром и не завершался. (упрощенно)
Поэтому целесообразно делать как удобнее/правильно, выбирая подходящий инструментарий.
From:exzerodivide
Date:Февраль, 8, 2017 21:22 (UTC)
(Link)
Кстати - про тонкую разницу между initrd и initramfs http://unix.stackexchange.com/questions/126217/when-would-you-use-pivot-root-over-switch-root
Что кстати говорит о том, что ничто не мешает стартовать с initramfs, подготовить из него новую rootfs, переключиться туда и почистить за собой хвосты. Вопрос - насколько это все с XIP живет.
[User Picture Icon]
From:kincajou
Date:Февраль, 8, 2017 21:48 (UTC)
(Link)
сначала, когда её неизвестно будет, как плата работает (и работает ли ваще), я всё равно буду всё в RAM держать, так что опробую все эти странные заклинания
From:exzerodivide
Date:Февраль, 8, 2017 21:57 (UTC)
(Link)
Я на самом деле со всеми этими штукам с загрузкой, подготовкой fs, рут_пивотом и так далее поупражнялся с одногруппником в рамках преддипломки в историко-физкультурном на кафедре теологииДавно это было, но что-то еще помню.
Мне кажется что все-таки заработает :-)
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