Различия

Здесь показаны различия между выбранной ревизией и текущей версией данной страницы.

Ссылка на это сравнение

setups:layered_fs [2016/02/26 17:42] (текущий)
Строка 1: Строка 1:
 +====== Как создаётся и работает слоистая файловая система Puppy. ======
  
 +===== Немного истории. =====
 +
 +Самые первые Puppy работали по принципу "ядро в рамдиске" (vmlinuz + initrd). Посмотреть можно на немецком сайте [[http://puppyfiles.org/isos/MicroMuppy/|MicroMuppy]]. По такому же принципу работает вполне современный [[http://distro.ibiblio.org/tinycorelinux/|TinyCore Linux]] размером 12Mb, [[http://uco.puppyrus.org/forum/thread180.html|обсуждение здесь]]. Но такая система на базе Puppy оказалась негибкой и Барри Каулер применил во второй версии Puppy [[wpru>UnionFS|unionfs]] а впоследствии [[wpru>Aufs|aufs]]. Этот революционный шаг и сделал Puppy столь популярным.
 +
 +===== Как это делается =====
 +
 +//Всё изложенное здесь относится к загрузке **FRUGAL**. При загрузке **FULL** производится монтирование раздела Puppy в корень как в любом обычном Linux, при этом initrd.gz не нужен (Во всяком случае так было со старыми версиями Puppy)//
 +
 +После загрузки и распаковки ядра (vmlinuz) и образа рамдиска (initrd.gz) мы имеем вполне работоспособную, но изолированную в оперативной памяти Linux-систему. Возможности этой системы сильно урезаны для уменьшения объёма и выполняет она одну задачу - создание слоистой файловой системы Puppy. Руководит этим процессом скрипт **init**. Первое, что делает **init**, определяет глобальные переменные и следом за этим "ищет связи с внешним миром", говоря технически устанавливает драйверы, необходимые для доступа к носителям информации (hd, sd, sr, flash).
 +
 +Следующим этапом является поиск файлов Puppy. Он может производиться на всех носителях или, для ускорения загрузки с заданного раздела (например **pdev1=sda2**) и заданного каталога (например **psubdir=puppy217**). Имена файлов для поиска берутся из файла **/DISTRO_SPECS** (впоследствии сохраняется как /etc/DISTRO_SPECS). Полученные данные записываются в файл **/tmp/PUPPYFILES**  (впоследствии сохраняется как /initrd/tmp/PUPPYFILES) и на основе их анализа выбирается способ загрузки Puppy - переменная **PUPMODE** (впоследствии записывается в /etc/rc.d/PUPSTATE). **PUPMODE** может принимать следующие значения:
 +  * PUPMODE=2  - Загрузка FULL (даже при отсутствии initrd.gz)
 +  * PUPMODE=5  - Первая (чистая) загрузка FRUGAL. Все изменения в системе сохраняются в **tmpfs**, по окончании сессии предлагается сохранить данные в файл сохранения.
 +  * PUPMODE=12 - Обычная загрузка FRUGAL. Все изменения в системе сразу записываются в файл сохранения.
 +  * PUPMODE=13 - Загрузка FRUGAL для флешек. Все изменения в системе сохраняются в **tmpfs**, по окончании заданного времени (по умолчанию 30 мин.) или окончании сессии все изменения в системе записываются в файл сохранения.
 +  * PUPMODE=77 - Загрузка FRUGAL для мультисессионного CD-RW. По окончании сессии все изменения в системе записываются в каталог на диске.
 +//**Примечание** - имя файла сохранения настроек обязательно содержит **$DISTRO_FILE_PREFIX** (берётся из /etc/DISTRO_SPECS), **_save**, произвольную часть задаваемую пользователем и расширения **.2fs .3fs .4fs** в зависимости от внутренней ФС файла сохранения. Например **pupm_save-mysavefile.3fs**.//
 +
 +==Подробнее==
 +
 +После загрузки драйверов носители информации становятся доступными для монтирования. Командой **init_probepart -k** получается список разделов и циклом производится их последовательное монтирование к /mnt/data. Командой **find** производится последовательный поиск файлов Puppy с записью каждого найденного файла в соответствующую этому файлу переменную. Если в строке загрузки указан параметр **psubdir**, то поиск производится только внутри указанного каталога. По окончании цикла переменные записываются в /tmp/PUPPYFILES. Если указан параметр **pdev1**, то командой **grep** удаляются все строки, не соответствующие шаблону **$PDEV1**\\
 +//Примечание. **$PDEV1** это указанное значение параметра **pdev1**. Например если в строке загрузки записано **pdev1=sda2**, то значением переменной **$PDEV1** будет **sda2**// \\
 +В зависимости от наличия и состава найденных файлов, а так же от параметра **pmedia** выбирается режим загрузки **PUPMODE** (значения смотрите выше), а в зависимости от числового значения **$PUPMODE** задаётся шаблон монтирования в виде набора переменных. Каждую переменную из набора обрабатывает свой участок скрипта **init** по соответствующему сценарию. В результате мы получаем набор каталогов **/pup_rw, /pup_ro2** и т. д. (зависит от $PUPMODE) с примонтированными к ним файлами Puppy. При значениях **PUPMODE=5** или **13** к /pup_rw монтируется **tmpfs**. Далее весь набор **pup_r* ** согласно очереди монтируется к /pup_new командой\\
 +  mount -t aufs -o udba=reval,diropq=w,dirs=${UMNTMAIN}${ZLAYER}${UMNTRO} unionfs /pup_new
 +где **${UMNTMAIN}** то, что грузится в верхние слои, например 1 и 2 /pup_rw=rw:/pup_ro2=ro:\\
 +**${ZLAYER}** (если есть) = /pup_ro3=rw: , **${UMNTRO}** - всё остальное с 4 слоя и ниже. Обычно это дополнительные модули.
 +
 +Последним выполняется **exec switch_root /pup_new /sbin/init** (смена корня) и мы уже в полноценной файловой системе Puppy. Дальнейшей загрузкой руководит **/etc/rc.d/sysinit**.
 +
 +===== Как это может быть сделано =====
 +
 +//Здесь описывается попытка создания своего скрипта init по более простому сценарию.//
 +
 +Если внимательно присмотреться к логике секций "Поиск файлов Puppy" и "Подключение файлов Puppy" то видно, что это "сетевое планирование", всеохватывающее и громоздкое. Кроме того создаётся множество "одноразовых" переменных. 
 +
 +Объединив поиск и подключение в одном цикле удалось избавиться от лишнего кода (450 строк против прежних 1500) и ускорить загрузку.
 +
 +Что сделано:
 +  *Для получения списка разделов вместо скриптового **probepart_init -k** применён **fdisk -l**, работающий гораздо быстрее, и применяется только при отсутствии **$PDEV1**
 +
 +  fdisk -l | grep ^/ | grep -v swap | cut -f 1 -d ' '
 +
 +  *Для исключения лишних монтирований  **$PDEV1** монтируется сразу к /mnt/dev_base и в случае обнаружения на разделе базового файла цикл прерывается командой **break**, отмонтирование не производится.
 +
 +  if [ "$PBASE" = "" ]; then
 +  umount /mnt/dev_base
 +  continue
 +  else
 +  echo "$PBASE" > /tmp/PUPPYFILES
 +  break
 +  fi
 +
 +  *Монтирование найденных файлов производится по мере их нахождения и, благодаря новому **busybox**, производится одной командой //(Приведён пример подключения базового файла)//
 +
 +  mount -o loop /mnt/dev_base$PSUBDIR/${DISTRO_FILE_PREFIX}-${DISTRO_VERSION}*.sfs /pup_ro2
 +
 +  *Переменная **${UMNTMAIN}** создаётся в процессе монтирования.
 +  *Для монтирования дополнительных модулей применена обрабатываемая циклом переменная **$EXTRASFSLIST**, которая формируется из:
 +   -переменной **$modules**, которая берётся из строки загрузки
 +   -списка модулей из каталога, указанного в переменной **$PFSDIR**
 +
 +  EXTRASFSLIST="$modules $(find /mnt/dev_base/${PFSDIR} -name *\.pfs -exec basename {} \;)"
 +
 +  *Переменная **${UMNTRO}** создаётся в процессе работы цикла обработки **$EXTRASFSLIST**
 +
 +Не реализован пока поиск save-файла, если он находится на другом разделе. Так же исключена загрузка по сети, сильно увеличивает размер initrd.gz из-за добавления драйверов, но это легко вернуть.
 +===== Как это работает =====
 +
 +Работает этот "слоистый бутерброд" довольно просто. Обращение к файлам происходит по полным путям (например /initrd/pup_ro2/etc/... или /mnt/.opera-12.11/...) согласно "очереди" aufs. Поиск идёт до первого совпадения. Поэтому одноимённые файлы из верхних слоёв закрывают файлы из нижних. При изменении файла он полностью записывается в верхний слой. При удалении файла, находящегося не в первом слое создаётся "тень" - скрытый файл **.wh.filename**, при удалении каталога - **.wh..wh.dirname**. Эти файлы прерывают поиск и файл или каталог как бы не существует в корне системы, хотя по полному пути его можно найти.
 +
 +
 +
 +===== Для тех, кто хочет подробнее =====
 +
 +Очень подробно ФС Puppy рассмотрена в статье Фарватера [[arc|"Архитектура файловой системы Puppy Linux"]].
Печать/экспорт