Различия

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

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

setups:arc [2016/02/26 17:42] (текущий)
Строка 1: Строка 1:
 +======Архитектура файловой системы Puppy Linux======
 +
 +=====С высоты птичьего полёта=====
 +Эта диаграмма --- картина файловой системы в целом:
 +
 +{{  pup2layers.png  }}
 +
 +На данной диаграмме каждый слой следует рассматривать как отдельную полноценную файловую систему с иерархией директорий от самого "/" (корня). Эти слои расположены друг над другом, и это достигается с применением файловой системы **[[wpru>UnionFS|UnionFS]]**. Довольно просто представить, как эта конструкция работает. Например, пусть на "розовом" уровне расположен файл ''/usr/lib/libgdkxft''. Он также будет виден и на "синем" уровне. Однако если синий уровень уже сам содержит файл с точно таким же названием, то он виден уже не будет, так как на него "наслоился" тот же самый файл с более верхнего ("розового") уровня.
 +
 +Вот описание каждого из уровней:
 +
 +  ; ramdisk : Это файловая система типа tmpfs, существующая в оперативной памяти, в которой создаются и изменяются файлы.
 +  ; pup_save.3fs : Этот файл --- постоянное хранилище, где все ваши данные, настройки, email, установленные пакеты и т.д. сохранены на постоянной основе. ".3fs" означает, что файл содержит файловую систему типа ext3.
 +  ; pup_xxx.sfs : Этот файл и есть Puppy. Встроенные приложения, оконный менеджер, скрипты --- всё это. Здесь ".sfs" означает, что данный файл содержит сжатую файловую систему типа squashfs, а "xxx" --- номер версии Puppy. Например, для Puppy 3.01 "ххх" будет "301".
 +  ; *_xxx.sfs : Эти файлы содержат дополнительные файловые системы типе squashfs. Здесь "*" может быть чем угодно. Например, devx_xxx.sfs --- полная среда программирования С/С++.
 +
 +Вот, что, однако, тут следует отметить. Всё это хозяйство находится "под ковром". Когда мы работаем с Puppy, то всё, что мы видим (с нашего верхнего уровня) --- это единая файловая система. Таким образом, в нашем примере, мы видим файл **/usr/lib/libgdkxft.so**, и для нас не будет иметь значения, на каком уровне он находится на самом деле.
 +
 +Заманчивая альтернатива уже существующей файловой системе **squashfs** --- использовать какой-нибудь существующий дистрибутив линукса (**underdog.lnx**) как нижний уровень для неё:
 +
 +{{  pup2underdog.png  }}
 +
 +Что приведенная выше диаграмма скрывает --- это то, что самый нижний уровень в данном случае ---  раздел диска, а не сам файл **underdog.lnx**. Сам файл **underdog.lnx** --- это просто текстовый файл, содержащий название этого раздела, например, **"hda1"**.
 +
 +При загрузке, Puppy прочитает файл **underdog.lnx** и смонтирует упомянутый в нём раздел как самый нижний уровень. Если окажется, что этот раздел содержит установленный на него дистрибутив линукса, то он целиком будет "просвечивать" через верхние уровни **unionfs** в Puppy.
 +
 +При этом, мы будем видеть, как мы запускаем JWM и/или что-то ещё, будем видеть наш рабочий стол, и одновременно целый дистрибутив (из нижнего уровня) будет также доступен нам для работы: все приложения, среды программирования, менеджеры пакетов, и т.д.
 +
 +Из первых двух диаграмм вы увидели, что уровни **unionfs** могут быть очень разными. В связи с этим (и еще с кое-чем другим), у Puppy появилась "переменная состояния" --- **PUPMODE**, которая показывает в каком состоянии (конфигурации слоёв) Puppy в настоящий момент запущен. Эта переменная определена в файле ''/etc/rc.d/PUPSTATE'' как целое число. Например, "12". Каждое значение **PUPMODE** требует отдельного описания.
 +
 +
 +=====Первичная загрузка с live-CD - PUPMODE 5=====
 +
 +Puppy запускается в этой конфигурации, когда вы впервые загружаете его с live-CD или USB-накопителя. Мы поговорим о примере с live-CD, поскольку наиболее вероятно, что это ваш самый первый опыт общения с Puppy.
 +
 +{{  pupmode5.png  }}
 +
 +В первый раз, когда вы вставляете live-CD и загружаетесь с него, у вас еще не определено никакого постоянного места хранения данных, и **unionfs** включает только два слоя: верхний --- ваши "файлы для работы" (файловая система типа **tmpfs** в оперативной памяти) и нижний --- **pup_xxx.sfs** (сжатая файловая система типа **squashfs** на live-CD), содержащий все файлы Puppy.  Эти два слоя оказываются наложенными друг на друга, начиная с корневой директории "/", однако, также могут быть рассмотрены независимо --- через их точки монтирования.  Файловая система **tmpfs** смонтирована на чтение и запись в точку ''/initrd/pup_rw'', а файловая система из **pup_xxx.sfs** смонтирована только на чтение в  точку ''/initrd/pup_ro2''.
 +
 +Таким образов, вы имеете возможность использовать Puppy, при этом не трогая ваш жесткий диск. Вы можете запускать приложения, конфигурировать, скачивать файлы из интернета, устанавливать пакеты, но всё это будет производиться только в **tmpfs** в оперативной памяти. Это и есть, так называемый, ramdisk. Объём рамдиска зависит от того, как много в вашем компьютере оперативной памяти (а еще, от того, есть ли у вас на жестких дисках своп-разделы линукса).
 +
 +Интересное начинается, когда вы собираетесь закончить работу и выключить компьютер. Тогда запускается скрипт выключения ''/etc/rc.d/rc.shutdown'', выводящий на экран окно, в котором спрашивает, хотите ли вы сохранить данную сессию. То есть, какие бы директории и  файлы ни были созданы в рамдиске, все они в тот момент могут быть сохранены.
 +
 +Тут появляется выбор. Если вы загрузились с live-CD, скорее всего, вы захотите сохраниться на жесткий диск, однако вы также можете выбрать и гибкий диск, USB-носитель, или даже тот же самый CD/DVD, с которого вы загрузились (при условии, что он записан в режиме мультисессии). Это очень просто: окно диалога предложит список разделов вам на выбор. При этом, окно диалога, также на выбор, предложит сохранить рамдиск вашей с сессией либо в виде файла, либо в виде раздела. В результате, например, будет создан файл **pup_save.3fs,** содержащий файловую систему **ext3**, размером 512МБ (как часто выбирают), или же, как альтернативу, вы выберите какой-либо существующий раздел, в который произведется сохранение. Часто выбор между файлом или разделом определяется  тем, содержит ли раздел файловую систему одного из линукс-совместимых типов (напр. ext2, ext3, reiserfs). Если доступны только файловые системы типа FAT, то подойдёт только вариант с созданием файла **pup_save.3fs**.
 +
 +Пока, допустим, мы  сохранились в этом файле.
 +
 +
 +=====Вторичная загрузка с live-CD - PUPMODE 12=====
 +
 +Итак, вы снова загружаете live-CD, зная, что сохранили свою предыдущую рабочую сессию в файле **pup_save.3fs** раздела жёсткого диска с файловой системой линукса, FAT, или NTFS. При этом Puppy загрузится в режиме **PUPMODE 12**.
 +
 +{{  pupmode12.png  |PUPMODE 12}}
 +
 +Что произошло? Puppy обнаружил файл **pup_save.3fs** на жестком диске и решил смонтировать файловую систему из  этого файла прямо в самый верхний уровень. Таким образом, тут нет никакого промежуточного рамдиска с его временной файловой системой **tmpfs**. Теперь в файл **pup_save.3fs **запись и чтение производятся напрямую. Этот сценарий очень подходит для загрузки на компьютерах с малым размером оперативной памяти. Рамдиск начальной стадии загрузки, то есть, файл **initrd.gz** присутствует в оперативной памяти, однако его размер составляет всего 1.9МБ.
 +
 +
 +=====Вторичная загрузка с USB - PUPMODE 13=====
 +
 +Если вы установили Puppy на USB-флеш-накопитель, то, используя Универсальный Инсталлятор или вручную, вы создали загрузочный носитель с файлами **vmlinuz** (ядро линукса), **initrd.gz** (рамдиск начальной загрузки), **pup_xxx.sfs** (файловая система типа **squashfs** со всеми файлами ОС Puppy) и syslinux.cfg (конфигурационный файл программы syslinux). Ситуация напоминает  таковую с live-CD --- при первой загрузке Puppy будет в состоянии **PUPMODE 5**, поскольку никаких постоянных хранилищ информации пока им не создано. При первом выключении, как описывалось выше в разделе про **PUPMODE 5**, вы создадите постоянное хранилище --- либо файл pup_save.3fs, либо целый раздел.
 +
 +При второй загрузке, Puppy обнаружит это постоянное хранилище, но в этом случае поймет, что сам-то он расположен на носителе, для которого следует серьёзно ограничивать частоту записи. Поэтому Puppy запустится в режиме **PUPMODE 13**.
 +
 +{{  pupmode13.png  |PUPMODE 13}}
 +
 +На приведенной диаграмме самый верхний слой занимает файловая система tmpfs рамдиска, в которую попадут все вновь созданные или модифицированные директории. Это --- рабочая зона, и она имеет потенциальные огранчения в соответствии с количеством доступной оперативной памяти. Но, конечно, если у вас на жестком диске есть готовый своп-раздел линукса, то Puppy его задействует для повышения эффективного размера рамдиска.
 +
 +В случае наличия постоянного хранилища информации на флеш-накопителе, смонтированном во втором уровне ("оранжевом"), Puppy будет сохранять в него всё с самого верхнего уровня с периодичностью в 30 минут. С точки зрения unionfs, второй уровень монтрован только для чтения, и только в самый верхний уровень разрешена запись, однако Puppy способен периодически брать верхний уровень целиком и "сливать" его на нижний уровень.
 +Тут надо отметить одну техническую особенность. "Сливать" --- это не совсем точное выражение. В идеале, этого хотелось бы --- сохранять всё на уровень постоянного хранения, и при этом каждый раз получать полностью свободный рамдиск. Тем не менее, когда я (Барри --- прим. перев.) попытался это сделать, то тем самым разрушил unionfs. Так что, компромисс заключается в том, что содержимое самого верхнего уровня //**копируется**// (а не перемещается-"сливается" --- прим. перев.) вниз на предыдущий уровень. И такой режим unionfs официально поддерживает.
 +Иными словами, это означает, что рамдиск никогда по-настоящему не "сливается", и если вы загрузили много всякой всячины или инсталлировали достаточно большой пакет, то он может забиться под завязку. Чтобы обойти эту проблему, в Puppy имеется программа, запущенная в фоновом режиме (демон), которая предупредит вас, если свободная оперативная память будет на исходе. И если так случилось, то ваше спасение просто: перезагрузитесь.
 +
 +Уточнение по поводу второго (сверху) уровня. Это --- постоянное хранилище, но, как обсуждалось выше в секции **PUPMODE 5**, при первом выключении вам предлагают создать такое хранилище либо в файле (**pup_save.3fs**), либо в разделе носителя информации. В последнем случае, рабочая сессия может быть сохранена в целом разделе, но только если это раздел с файловой системой линукса. Тогда то, что монтируется как второй уровень будет разделом, а не файлом.
 +В случае загрузки с USB-флеш накопителя, использовать целый раздел носителя для хранения персональных данных было бы очень неплохо. Файл **pup_save.3fs** имеет ограниченный размер, обычно 512МБ или еще меньше, если на разделе накопителя, куда он сохраняется, не так много свободного места. Кроме того, были сообщения на Puppy-форуме, что этот файл может быть увеличен только до размера 750МБ--1ГБ. Ну, полагаю, что последнее --- не самая страшная проблема для большинства флеш-накопителей. 
 +
 +Если вы выбрали сохранение рабочей сессии прямо на раздел USB-носителя, то это должен быть линукс-раздел, то есть раздел с файловой системой **ext2**, **ext3**, или **reiserfs**. В то же время, сохранение файла **pup_save.3fs**  может производиться на любой тип раздела накопителя --- их обычно выпускают с файловой системой FAT16, что вполне подойдёт.
 +
 +
 +=====Полная инсталляция - PUPMODE 2=====
 +
 +Многие пользователи Puppy знают, что существует 2 способа установки Puppy на жесткий диск: то, что мы называем "опицией 1" и "опцией 2".
 +
 +Опция 1 --- выбор с наименьшим проникновением в систему (наименее инвазивный), при котором просто производится копирование файлов **vmlinuz, initrd.gz  **и** pup_xxx.sfs** в выбранный раздел носителя. Чтобы загружать Puppy, установленный таким способом, Универсальный Установщик предлагает создать загрузочный гибкий диск. Однако, в настоящий момент, загрузочный гибкий диск может загрузить только тот Puppy, который установлен на раздел с файловой системой FAT. Для загрузки Puppy также возможно сконфигурировать программы Grub или Lilo. Преимущество данной опции в том, что при таком раскладе установка Puppy никак не влияет на какие-либо другие разделы носителя, и, если на них уже  установлены Windows или другие дистрибутивы Linux, то они останутся совершенно нетронутыми. При Опции 1 загрузка Puppy проходит в режиме **PUPMODE12**.
 +
 +Опция 2 означает, что Puppy устанавливается на целый раздел, который должен быть линукс-разделом (**ext2, ext3, reiserfs**). Это рекомендуется разработчикам или вообще всем, кто собирается компилировать программы, так как такой способ экономит свободное место на диске.
 +
 +{{  pupmode2.png  |PUPMODE 2}}
 +
 +Это --- самая простая конфигурация из всех. Нет никакого рамдиска, а сам раздел смонтирован прямо на самый верхний уровень. На самом деле, если не надо загружать никаких **".sfs"**, то Puppy не будет использовать **unionfs**, поскольку нет никаких слоев.
 +
 +**PDEV1** , обозначенная на диаграмме --- просто переменная в файле ''/etc/rc.d/PUPSTATE'', содержащая название раздела, например **hda1**, который монтируется прямо в **"/"** (корень). Но как узнать, какое значение примет **PDEV1 ** во время загрузки? Утверждать, что   это значение записано в файле **/etc/rc.d/PUPSTATE**  , который находится на загружаемом разделе --- это все равно, что говорить, что яйцо было раньше курицы (яйцо действительно было раньше курицы, но Барри об этом, видимо, не знал --- прим перев). Этот файл, в действительности существует только для скриптов, которым нужно знать, откуда Puppy загрузился. В данном случае, Puppy загружается с гибкого диска, с загрузочного USB-флеш накопителя или с помощью Grub или Lilo. Универсальный Установщик дает возможность задействовать на выбор: гибкий диск, USB или Grub.
 +
 +
 +=====Мультисессия на CD/DVD - PUPMODE 77=====
 +
 +Данный режим используется для мультисессионных CD и DVD. В этом случае, наше постоянное хранилище состоит из папок на CD/DVD. Каждый раз при вылючении сессия сохраняется в физически новых папках, так что последние постепенно накапливаются на CD/DVD. При загрузке, эти папки считываются системой в обратном порядке и загружаются в рамдиск.
 +
 +{{  pupmode77.png  |PUPMODE 77}}
 +
 +Считваются они во второй уровень ("оранжевый"). Во время рабочей сессии, вновь созданные, а также изменённые директории и файлы будут записаны в самый верхний ("зеленый") уровень. При выключении, этот уровень записывается на CD/DVD как новая папка.
 +
 +
 +=====Логика в нумерации режимов PUPMODE=====
 +
 +Недавно я обсуждал режимы **PUPMODE** с пользователем **Phil** на форуме Puppy. Он загрузил **Puppy2**, используя **GRUB** , при этом имея **initrd.gz**, **vmlinuz** и **pup_xxx.sfs** (т.е все необходимые файлы Puppy) на одном из разделов жесткого диска. После этого  он сохранил рабочую сессию прямо в загрузочный раздел.
 +
 +Будем считать, что раздел называется **/dev/hda2**. Тогда ситуация выглядит так:
 +
 +  partition hda2
 +  все сохраненные сессии тут, включая файл /etc/puppyversion.
 +  /initrd.gz
 +  /pup_xxx.sfs
 +  /vmlinuz
 +
 +Я упомянул файл ''/etc/puppyversion'', поскольку он сохраняется во время каждой сессии, и Puppy ищет его при загрузке, чтобы определить, имеются ли в данном разделе диска файлы, сохраненные Puppy.
 +Обратите внимание, что файлы **initrd.gz, pup_xxx.sfs **и **vmlinuz** могут находиться в папках, например в **/boot**, при условии, конечно, что для этого вы также сконфигурируете **GRUB** соответствующим образом.
 +В случае **Phil**, Puppy запустится в режиме PUPMODE 7, но чем это определяется? Какая логика стоит за этим?
 +
 +**PUPMODE** --- это двоичное число, где каждый бит (под номером ... 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0) является флагом:
 +
 +^  БИТ  ^  ДЕСЯТ.ВЕЛИЧИНА  ^  ЗНАЧЕНИЕ  ^
 +| 0 | 1 | используется для самого верхнего уровня tmpfs (/initrd/pup_rw) системы unionfs. |
 +| 1 | 2 | загрзочный раздел (PDEV1) содержит сохранённые сессии Puppy. |
 +| 2 | 4 | в загрузочном разделе (PDEV1) существует файл pup_xxx.sfs |
 +| 3 | 8 | существует файл pup_save.3fs (в котором сохранены сессии). |
 +| 4 | 16 | |
 +| 5 | 32 | |
 +| 6 | 64 | флаг мультисессий. |
 +
 +Например, мульсессионный CD/DVD запускается с **PUPMODE=77**, что есть 1+4+8+64. Вполне логично, как видите.
 +
 +В случае **Phil**, Puppy запустится в режиме **PUPMODE=6 (2+4)**, и, поскольку сохранённые сессии находятся на быстром носителе с неограниченным возможным числом операций записи, то тогда становится не нужно хранить в оперативной памяти самый верхний уровень --- **tmpfs**. Обратите внимание, что этот **tmpfs** используется как промежуточное депо для сохранения рабочих файлов и директорий, и его существование оправдано только тогда, когда мы органичены по числу записей на носитель (напр. Флеш-память), или, когда текущая сессия должна быть сохранена на очень медленный носитель и/или только в строго определённое время (запись на дорожку мультисессионного CD/DVD), или же, когда мы заведомо хотим использовать всю систему, загруженной прямо в память (как бывает при первой загрузке Puppy).
 +
 +Полная инсталляция Puppy **("опция 2")** запускается в режиме **PUPMODE 2**.
 +
 +Решение о том, какой режим загрузки использовать, принимается внутри первого заргузочного скрипта **/initrd/sbin/init**.
 +
 +Хотя, в случае полной установки на жесткий диск, файл **initrd.gz** не используется совсем, и первым запущенным скриптом является ''/etc/rc.d/rc.sysinit''. Puppy полагает **PUPMODE=2.**
 +
 +
 +=====Начальный рамдиск=====
 +
 +Первое событие, которое происходит при загрузке системы --- это загрузка ядра линукса **vmlinuz** в оперативную память. За ним идет начальный рамдиск, который находиться в файле **initrd.gz**.
 +Обратите внимание, что исключение составляет **PUPMODE 2**, т.е. вариант полной инсталляции на жесткий диск, в случае которой отдельного файла **initrd.gz** не существует (не совсем понимаю, что Барри имеет в виду, т.к., из моего личного опыта, при полной инсталляции, такой файл существует, правда, не обязательно в корневой директории раздела, а в там, откуда загружается **GRUB.**  --- прим. перев.).
 +Когда начальный рамдиск загружен, на выполнение запускается скрипт **/sbin/init**. Ниже этот скрипт приведен в упрощенном виде для иллюстрации.
 +
 +<code bash>
 +#!/bin/ash<BR>#(c) Copyright 2006 Barry Kauler, www.puppylinux.com
 +PATH="/bin:/sbin"
 +KERNVER="`uname -r`"
 +
 +#Параметры загрузки PMEDIA= usbflash|usbhd|usbcd|ideflash|idehd|idecd|idezip|satahd|scsihd|scsicd
 +#уровни unionfs:              RW            RO1             RO2             PUPMODE
 +#только PUPSFS:               tmpfs                         pup_xxx.sfs      5
 +#PDEV1 с puppy:               tmpfs         PDEV1*                           3
 +#PDEV1 с puppy, без tmpfs:    PDEV1                                          2
 +#PDEV1, PUPSFS:               tmpfs         PDEV1*          pup_xxx.sfs      7
 +#уровни unionfs:              RW            RO1             RO2              PUPMODE
 +#найденный PUPSFS, PUPSAVE:   tmpfs         pup_save.3fs*   pup_xxx.sfs      13
 +#PUPSAVE(мульти), PUPSFS:     tmpfs         folders(tmpfs2) pup_xxx.sfs      13+64 = 77
 +#PUPSAVE, PUPSFS, no tmpfs:   pup_save.3fs                  pup_xxx.sfs      12
 +
 +fsfunc() #аргумент этой функции --- тип файловой системы
 +{
 + FSTYPE="$1"
 + [ "$FSTYPE" = "Ext2" ] && FSTYPE="ext2"
 + [ "$FSTYPE" = "ReiserFS" ] && FSTYPE="reiserfs"
 + [ "$FSTYPE" = "Ext3" ] && FSTYPE="ext3"
 + [ "$FSTYPE" = "FAT16" ] && FSTYPE="vfat"
 + [ "$FSTYPE" = "FAT32" ] && FSTYPE="vfat"
 + [ "$FSTYPE" = "NTFS" ] && FSTYPE="ntfs"
 + [ "$FSTYPE" = "ISO9660" ] &&  FSTYPE="iso9660"
 +}
 +
 +guesspmediafunc() {
 + код для определения PMEDIA, если этот параметр не задан при загрузке ядра
 +}
 +
 +ispupfunc() #fstype partition
 +{
 + код для поиска постоянного хранилища(раздела)
 +}
 +
 +searchsavefunc() {
 + код для поиска постоянного хранилища в виде фаила pup_save.3fs
 +}
 +
 +findpupfunc() #аргументы --- список дисков (не разделов!) для поиска
 +{
 + код для поиска загрузочного раздела и загрузоных файлов puppy
 +}
 +
 +loadfolders() { #арг.: папка-источник, целевая-папка
 + код для загрузки папок с сохраненными сессиями на мультисессионных CD/DVD
 +}
 +
 +mount -t proc none /proc
 +PUPPYVERSION="`cat /PUPPYVERSION`"
 +
 +####ЗАГРУЗКА МОДУЛЕЙ###########################################
 +
 +код для загрузки модулей ядра
 +
 +###########################################################
 +
 +PDEV1=""
 +case $PMEDIA in
 + idecd)
 +  CDDRIVES="`test-eide | grep '\- cdrom \-' | cut -f 1 -d " " | cut -f 3 -d "/" | tr "\n" " "`"
 +  findpupfunc $CDDRIVES
 +  #возвращает, например: PDEV1=hdc FSTYPE=iso9660 PUPSFS=pup_001.sfs
 +  [ ! "$PUPSAVE" ] && searchsavefunc #search for PUPSAVE.
 +  ;;
 + idehd)
 +  HDDRIVES="`test-eide | grep '\- disk \-' | cut -f 1 -d " " | cut -f 3 -d "/" | tr "\n" " "`"
 +  findpupfunc $HDDRIVES
 +  #возвращает, например: PDEV1=hda3 FSTYPE=ext3 PUPSFS=pup_001.sfs
 +  ;;
 + usbflash)
 +  #тут может быть и "superfloppy" без mbr и разделов.
 +  USBDRIVES="`cat /proc/partitions | grep "sd[a-z]$" | tr -s " " | cut -f 5 -d " " | tr "\n" " "`"
 +  findpupfunc $USBDRIVES
 +  #возвращает, например: PDEV1=sda1 FSTYPE=ext2 PUPSFS=pup_001.sfs DEV1PUP=""
 +  ;;
 + ideflash)
 +  #Похоже, обычный диск IDE. Однако, для него может потребоваться параметр загрузки ядра "ide=nodma" 
 +  HDDRIVES="`test-eide | grep '\- disk \-' | cut -f 1 -d " " | cut -f 3 -d "/" | tr "\n" " "`"
 +  findpupfunc $HDDRIVES
 +  #возвращает, например: PDEV1=hda1 FSTYPE=ext3 PUPSFS=pup_001.sfs
 +  ;;
 + idezip) код
 +  ;;
 + satahd) код
 +  ;;
 + satacd) код
 +  ;;
 + usbhd) код
 +  ;;
 + *)
 +  #загрузим носитель usb...
 +  usbstoragefunc #loads usb-storage.o 
 +  ALLDRIVES="`probedisk | grep '^/dev/' | cut -f 1 -d '|' | cut -f 3 -d '/' | tr "\n" " "`"
 +  findpupfunc $ALLDRIVES
 +  #возвращает, например: PDEV1=hdc FSTYPE=iso9660 PUPSFS=pup_001.sfs
 +  guesspmediafunc
 +  [ ! "$PUPSAVE" ] && searchsavefunc #search for PUPSAVE.
 +  ;;
 +esac
 +#выходим с PDEV1=полное-имя-устройства
 +
 +#всего оперативной памяти, кроме зарезервированной под видеопамять
 +PCRAMSIZE=`free | head -n 2 | tail -n 1 | tr -s " " | cut -f 3 -d " "`
 +SIZEFILLK=`expr $PCRAMSIZE \/ 2` #половина памяти.
 +#для машин с 128M оперативной памяти надо извернуться, чтобы загрузить pup_xxx.sfs в память.
 +if [ $SIZEFILLK -gt 50000 ];then
 + [ $SIZEFILLK -lt 70000 ] && SIZEFILLK=71680 #70M.
 +fi
 +PHYSICALFILLK="$SIZEFILLK"
 +
 +#узнаем, есть ли доступный нам своп-раздел
 +SWAPINFO="`fdisk -l | grep "Linux swap" | head -n 1`"
 +if [ ! "$SWAPINFO" = "" ];then
 + #теперь мы можем сделать действительно большой рамдиск
 + SWAPPART="`echo "$SWAPINFO" | cut -f 1 -d " "`"
 + SWAPSIZE=`fdisk -s $SWAPPART`
 + SWAPSIZ4=`expr $SWAPSIZE \/ 4`
 + SWAPSIZ2=`expr $SWAPSIZE \/ 2`
 + SWAPSIZE=`expr $SWAPSIZ2 + $SWAPSIZ4` #3/4 of original
 + SIZEFILLK=`expr $SIZEFILLK + $SWAPSIZE`
 + echo "Загружаю своп-раздел $SWAPPART..."
 + swapon $SWAPPART
 +fi
 +
 +#монтируем главную файловую систему Puppy
 +PUPMODE=1                                             #используем tmpfs.
 +[ "$DEV1PUP" = "yes" ] && PUPMODE=`expr $PUPMODE + 2` #PDEV1 с puppy installed.
 +[ "$PUPSFS" ] && PUPMODE=`expr $PUPMODE + 4`           #pup_xxx.sfs exists (on PDEV1).
 +[ "$PUPSAVE" ] && PUPMODE=`expr $PUPMODE + 8`          #pup_save.3fs exists.
 +if [ $PUPMODE -eq 13 ];then
 + #multisession cd, run in PUPMODE 13+64=77
 + [ ! "`echo -n "$PUPSAVE" | grep '/20[0-9][0-9]'`" = "" ] && PUPMODE=77
 +fi
 +
 +UMNT1='/pup_rw=rw'
 +DEV1MNT="/pup_ro1"
 +case $PUPMODE in
 + 3) #PDEV1 с puppy, и испольуем tmpfs (возможно).
 +  echo -n "Mounting /dev/${PDEV1}..."
 +  if [ ! "`echo -n "$PMEDIA" | grep --extended-regexp "idehd|satahd|scsihd"`" = "" ];then
 +  #не использовать unionfs, а просто монтироваться на /pup_new вместо /pup_rw
 +   mount -o rw -t $FSTYPE /dev/$PDEV1 /pup_new
 +   PUPMODE=2
 +  else
 +   mount -o ro -t $FSTYPE /dev/$PDEV1 /pup_ro1
 +   mount tmpfs /pup_rw -t tmpfs -o size=${SIZEFILLK}k
 +   UMNT1='/pup_rw=rw:/pup_ro1=ro'
 +  fi
 +  ;;
 + 5) #есть tmpfs, нет уровня для постоянного хранения, есть pup_xxx.sfs
 +  # ***ПРИ ПЕРВОМ ЗАПУСКЕ***
 +  echo -n "Монтирую ${PDEV1}..."
 +  mount -o rw,noatime -t $FSTYPE /dev/$PDEV1 /mnt/dev_ro1
 +  echo -n "Монтирую tmpfs..."
 +  mount tmpfs /pup_rw -t tmpfs -o size=${SIZEFILLK}k
 +  UMNT1='/pup_rw=rw:/pup_ro2=ro' 
 + #если хватит места в рамдиске, тогда скопируем эту ф.с.
 +  if [ $SIZEFILLK -gt `du /mnt/dev_ro1/$PUPSFS | cut -f 1` ];then
 +   echo -n "Копирую $PUPSFS в рамдиск..."
 +   cp -f /mnt/dev_ro1/$PUPSFS /pup_rw/
 +   sync
 +   losetup /dev/loop0 /pup_rw/$PUPSFS
 +   echo "Размонтирую ${PDEV1}..."
 +   umount /dev/$PDEV1
 +  else
 +   echo -n "Монтирую $PUPSFS прямо с /dev/$PDEV1..."
 +   losetup /dev/loop0 /mnt/dev_ro1/$PUPSFS
 +  fi
 +  mount -r -t squashfs -o noatime /dev/loop0 /pup_ro2
 +  ;;
 + 7) #есть tmpfs, есть PDEV1 - постоянное хранилище, есть pup_xxx.sfs.
 +  echo -n "Монтирую /dev/${PDEV1}..."
 +  mount -o rw -t $FSTYPE /dev/$PDEV1 /pup_ro1
 +  echo -n "Монтирую tmpfs..."
 +  mount tmpfs /pup_rw -t tmpfs -o size=${SIZEFILLK}k
 +  UMNT1='/pup_rw=rw:/pup_ro1=ro:/pup_ro2=ro'
 +  #если хватает места в рамдиске, скопируем туда эту ф.с.
 +  if [ $SIZEFILLK -gt `du /pup_ro1/$PUPSFS | cut -f 1` ];then
 +   echo "Копирую $PUPSFS в рамдиск..."
 +   cp -f /pup_ro1/$PUPSFS /pup_rw/
 +   sync
 +   losetup /dev/loop0 /pup_rw/$PUPSFS
 +  else
 +   echo "Монтирую $PUPSFS прямо с /dev/$PDEV1..."
 +   losetup /dev/loop0 /pup_ro1/$PUPSFS
 +  fi
 +  echo -n "Монтирую ${PUPSFS}..."
 +  mount -r -t squashfs -o noatime /dev/loop0 /pup_ro2
 +  ;;
 + 13) #есть tmpfs, есть pup_save.3fs - постоянное хранилище, есть pup_xxx.sfs.
 +  SAVEFS="`echo -n "$PUPSAVE" | cut -f 1 -d ','`"  #ф.с. и раздел, где расположен pup_save.3fs
 +  SAVEPART="`echo -n "$PUPSAVE" | cut -f 2 -d ','`"
 +  SAVEFILE="`echo -n "$PUPSAVE" | cut -f 3 -d ','`"
 +  echo -n "Монтирую ${PDEV1}..."
 +  mount -o rw,noatime -t $FSTYPE /dev/$PDEV1 /mnt/dev_ro1
 +  TMPFSMNT="/pup_rw" #tmpfs --- на самый верх
 +  EFSMNT="/pup_ro1"  #pup_save.3fs на следующий уровень
 +  UMNT1='/pup_rw=rw:/pup_ro1=ro:/pup_ro2=ro'
 +  #возможно, скатимся на PUPMODE=12...
 +  if [ ! "`echo -n "$PMEDIA" | grep --extended-regexp "idecd|usbcd|scsicd"`" = "" ];then
 +   #Грузимся с cd. Если есть pup_save.3fs на быстром носителе, загружаем его напрямую
 +   [ ! "`echo -n "$SAVEPART" | grep '^hd'`" = "" ] && SAVEDIRECT="yes"
 +  fi
 +  if [ ! "`echo -n "$PMEDIA" | grep --extended-regexp "idehd|satahd|scsihd"`" = "" ];then
 +   #полагаем, что pup_save.3fs присутствует на этом быстром носителе
 +   SAVEDIRECT="yes"
 +  fi
 +  if [ "$SAVEDIRECT" = "yes" ];then
 +   #pup_save.sfs находится на быстром носителе, что позволяет неограниченно записывать,  значит tmpfs больше не нужна
 +   PUPMODE=12 #rc.shutdown не надо будет ничего сохранять
 +   #still need a tmpfs, to load pup_xxx.sfs...
 +   TMPFSMNT="/mnt/tmpfs" #tmpfs создана где-то еще
 +   EFSMNT="/pup_rw"      #pup_save.3fs на самом верхнем уровне
 +   UMNT1='/pup_rw=rw:/pup_ro2=ro'
 +  fi
 +  echo -n "Монтирую tmpfs..."
 +  mount tmpfs $TMPFSMNT -t tmpfs -o size=${SIZEFILLK}k
 +  #если достаточно места на рамдиске, скопируем эту ф.с
 +  if [ $SIZEFILLK -gt `du /mnt/dev_ro1/$PUPSFS | cut -f 1` ];then
 +   echo -n "Копирую $PUPSFS на рамсдиск..."
 +   cp -f /mnt/dev_ro1/$PUPSFS $TMPFSMNT/
 +   sync
 +   losetup /dev/loop0 $TMPFSMNT/$PUPSFS
 +   umount /dev/$PDEV1
 +  else
 +   echo -n "Монтирую $PUPSFS прямо с /dev/$PDEV1..."
 +   losetup /dev/loop0 /mnt/dev_ro1/$PUPSFS
 +  fi
 +  mount -r -t squashfs -o noatime /dev/loop0 /pup_ro2
 +  #теперь сделаем PUPSAVE...
 +  SMNTPT="`mount | grep "/dev/$SAVEPART" | tr -s " " | cut -f 3 -d " "`"
 +  if [ "$SMNTPT" = "" ];then
 +   SMNTPT="/mnt/dev_save"
 +   mount -t $SAVEFS -o noatime,rw /dev/$SAVEPART /mnt/dev_save
 +  fi
 +  #собираемся смонтировать pup_save.3fs, но перед тем проверим, надо ли изменить его размер
 +  if [ -f $SMNTPT/pupsaveresize.txt ];then
 +   KILOBIG=`cat $SMNTPT/pupsaveresize.txt`
 +   rm -f $SMNTPT/pupsaveresize.txt
 +   echo "Увеличиваем $SAVEFILE на $KILOBIG Кбайт, п-ста, подождите..."
 +   dd if=/dev/zero bs=1k count=$KILOBIG | tee -a $SMNTPT$SAVEFILE > /dev/null
 +   sync
 +   e2fsck -y -f $SMNTPT$SAVEFILE
 +   resize2fs -pf $SMNTPT$SAVEFILE #если нет размера, мы заполним файл целиком
 +   sync
 +   sleep 6 #так мы сможем увидеть результат
 +  fi
 +  losetup /dev/loop1 $SMNTPT$SAVEFILE
 +  echo -n "Монтируем ${SAVEFILE}..."
 +  FILEFS="ext3"
 +  [ ! "`echo -n "$SAVEFILE" | grep "2fs"`" = "" ] && FILEFS="ext2"
 +  mount -t $FILEFS -o noatime,rw /dev/loop1 $EFSMNT
 +  ;;
 + 77) #multisession cd/dvd
 +  SAVEFS="`echo -n "$PUPSAVE" | cut -f 1 -d ','`"   #ф.с. И раздел, где расположен файл pup_save.3fs
 +  SAVEPART="`echo -n "$PUPSAVE" | cut -f 2 -d ','`" # "
 +  SAVEFILE="`echo -n "$PUPSAVE" | cut -f 3 -d ','`"
 +  echo -n "Монтирую ${PDEV1}..."
 +  mount -o rw,noatime -t $FSTYPE /dev/$PDEV1 /mnt/dev_ro1;check_status $?
 +  TMPFSMNT="/pup_rw" #tmpfs --- на самый верхний уровень
 +  EFSMNT="/pup_ro1"  #папки с cd - на следующий уровень
 +  UMNT1='/pup_rw=rw:/pup_ro1=ro:/pup_ro2=ro'
 +  #выполним PUPSAVE...
 +  SMNTPT="`mount | grep "/dev/$SAVEPART" | tr -s " " | cut -f 3 -d " "`"
 +  if [ "$SMNTPT" = "" ];then
 +   SMNTPT="/mnt/dev_save"
 +   mount -t $SAVEFS -o noatime,rw /dev/$SAVEPART /mnt/dev_save
 +  fi
 +  #личные данные сохранены в датированных папках
 +  #создадим tmpfs на /pup_ro1 и загрузим в нее папки только в физической памяти
 +  ALMOSTFILLK=`expr $PHYSICALFILLK \/ 4`
 +  ALMOSTFILLK=`expr $PHYSICALFILLK - $ALMOSTFILLK`
 +  mount tmpfs /pup_ro1 -t tmpfs -o size=${ALMOSTFILLK}k;check_status $?
 +  loadfolders $SMNTPT /pup_ro1
 +  ALMOSTFILLK=`free | grep 'Mem:' | tr -s " " | cut -f 5 -d " "`
 +  ALMOSTFILLK=`expr $ALMOSTFILLK \/ 2`
 +  SIZEFILLK=`expr $ALMOSTFILLK + $SWAPSIZE`
 +  echo -n "Mounting tmpfs..."
 +  mount tmpfs $TMPFSMNT -t tmpfs -o size=${SIZEFILLK}k;check_status $?
 +  #if enough room in ramdisk, copy it...
 +  if [ $SIZEFILLK -gt `du /mnt/dev_ro1/$PUPSFS | cut -f 1` ];then
 +   echo -n "Copying $PUPSFS to ramdisk..."
 +   cp -f /mnt/dev_ro1/$PUPSFS $TMPFSMNT/
 +   sync
 +   losetup /dev/loop0 $TMPFSMNT/$PUPSFS
 +   umount /dev/$PDEV1
 +  else
 +   echo -n "Монтируем $PUPSFS прямо с /dev/$PDEV1..."
 +   losetup /dev/loop0 /mnt/dev_ro1/$PUPSFS
 +  fi
 +  mount -r -t squashfs -o noatime /dev/loop0 /pup_ro2;check_status $?
 +  sync
 +  umount /dev/$SAVEPART 2>/dev/null
 +  ;;
 + *) #неполная комбинация
 +  #некуда сохранять и/или puppy не найден.
 +  echo "ОШИБКА, не могу найти Puppy на носителе $PMEDIA."
 +  echo "PUPMODE=$PUPMODE PDEV1=$PDEV1"
 +  sleep 10
 +  exit
 +  ;;
 +esac
 +
 +UMNTRO=""
 +#Ищем *_$PUPPYVERSION.sfs (ex: dev_200.sfs)...
 +[ $PUPMODE -eq 7 ] && EXTRASFS="/pup_ro1"
 +[ $PUPMODE -eq 13 ] && EXTRASFS="`mount | grep "/dev/$SAVEPART" 2>/dev/null | tr -s " " | cut -f 3 -d " "`"
 +[ $PUPMODE -eq 77 ] && EXTRASFS="`mount | grep "/dev/$SAVEPART" 2>/dev/null | tr -s " " | cut -f 3 -d " "`"
 +if [ "$EXTRASFS" ];then
 + cd $EXTRASFS
 + if [ -f underdog.lnx ];then
 +  #вот тут релизована идея загружать Puppy поверх других дистрибутивов линукса
 +  UNDERDOGPART="`cat underdog.lnx`"
 +  UDMNTPT="`mount | grep "/dev/$UNDERDOGPART" | tr -s " " | cut -f 3 -d " "`"
 +  if [ "$UDMNTPT" = "" ];then
 +   UNDERDOGFS="`disktype /dev/$UNDERDOGPART | grep 'file system' | head -n 1 | cut -f 1 -d " "`"
 +   [ "$UNDERDOGFS" = "Ext2" ] && UNDERDOGFS="ext2"
 +   [ "$UNDERDOGFS" = "Ext3" ] && UNDERDOGFS="ext3"
 +   [ "$UNDERDOGFS" = "Reiserfs" ] && UNDERDOGFS="reiserfs"
 +   if [ ! "`echo -n "$UNDERDOGFS" | grep --extended-regexp 'ext2|ext3|reiserfs'`" = "" ];then
 +    mount -r -t $UNDERDOGFS /dev/$UNDERDOGPART /pup_ro3
 +    if [ $? -eq 0 ];then
 +     UMNTRO="${UMNTRO}:/pup_ro3=ro"
 +     #fixes to prevent library clashes...
 +     MNTFIX='/pup_rw'
 +     [ ! "`echo -n "$UMNTRO" | grep 'pup_ro1'`" = "" ] && MNTFIX='/pup_ro1'
 +     [ ! -f $MNTFIX/lib/.wh.i686 ] && touch $MNTFIX/lib/.wh.i686 #hides /lib/i686
 +     #puppy needs dir name /usr/lib/qt at bootup (see rc.profile)...
 +     REALQTDIR="`find /pup_ro3/usr/lib -maxdepth 1 -type d -name qt* | tail -n 1 | sed -e 's/\/pup_ro3\/usr\/lib\///g'`"
 +     if [ "$REALQTDIR" ];then
 +      if [ ! -e $MNTFIX/usr/lib/qt ];then
 +       [ "`find /pup_ro3/usr/lib -maxdepth 1 -xtype d -name qt`" = "" ] && ln -s $REALQTDIR $MNTFIX/usr/lib/qt
 +      fi
 +     fi
 +    fi
 +   fi
 +  else
 +   UMNTRO="${UMNTRO}:${UDMNTPT}=ro"
 +  fi
 +
 + else
 +  CNTLOOP=3
 +  for ONESFS in `ls -1 *_${PUPPYVERSION}.sfs | grep -v "^pup_" | tr "\n" " "`
 +  do
 +   losetup-FULL /dev/loop${CNTLOOP} $EXTRASFS/$ONESFS
 +   mount -r -t squashfs -o noatime /dev/loop${CNTLOOP} /pup_ro${CNTLOOP}
 +   [ $? -eq 0 ] && UMNTRO="${UMNTRO}:/pup_ro${CNTLOOP}=ro"
 +   CNTLOOP=`expr $CNTLOOP + 1`
 +  done
 + fi
 + cd /
 +fi
 +
 +#теперь создадим unionfs...
 +mkdir -p /pup_rw/etc/rc.d
 +echo -n "$PUPMODE" > /pup_rw/etc/rc.d/PUPMODE #его прочитает rc.shutdown.
 +echo -n "$PDEV1" > /pup_rw/etc/rc.d/PDEV1     # "
 +echo -n "$FSTYPE" > /pup_rw/etc/rc.d/DEV1FS     # "
 +echo -n "$PUPSFS" > /pup_rw/etc/rc.d/PUPSFS   # "
 +echo -n "$PUPSAVE" > /pup_rw/etc/rc.d/PUPSAVE # "
 +echo -n "$PMEDIA" > /pup_rw/etc/rc.d/PMEDIA   # "
 +echo -n "$PUPPYVERSION" > /pup_rw/etc/puppyversion #для проверки на наличие сохраненных сессий при загрузке (ispupfunc)
 +mkdir /pup_rw/initrd
 +sync
 +echo -n "Создаем unionfs с локальным корнем в директории /pup_new..."
 +mount -t unionfs -o dirs=${UMNT1}${UMNTRO} none /pup_new
 +
 +#надо запустить dnotify из скрипта загрузки...
 +#/sbin/launchpupsafe &
 +
 +cd /pup_new
 +sync
 +umount /proc
 +#echo "pivot_root переводит загрузку из началького рамдиска в директорию /pup_new..."
 +pivot_root . initrd
 +exec chroot . sh -c "exec /bin/busybox init"  <dev/console >dev/console 2>&1
 +</code>
 +
 +Похоже, тут много чего происходит! Но, на самом деле, всё это довольно просто. По сути, скрипт ищет загрузочный раздел и файл-хранилище или раздел-хранилище, используя параметр загрузки **PMEDIA** как ориентир. А когда находит их, то определяет соотвтствующий **PUPMODE**, а затем создает необхдимые уровни **unionfs**. В самом конце, скрипт выполняет команду **pivot_root**, которая подключает директорию **/pup_new** в качестве нового **"/"** корня  файловой системы. Эта директория **/pup_new** --- то место, где слиты воедино все слои **unionfs**. 
 +
 +Начальный рамдиск оставлен в памяти, и после работы **pivot_root** он будет перемещен в директорию **/initrd**. То есть, всё, что было "/", после **pivot_root**  будет в  **/initrd**. И именно в **/initrd** вы сможете потом получить доступ к слоям по-отдельности. Хотя последнее представляет интерес скорее для разработчиков, чем для пользователей. 
 +
 +Следующий, исполняющийся после **pivot_root** скрипт --- это **/etc/rc.d/rc.sysinit**. Обратите внимание, что всё внутри директории **/etc/rc.d** можно редактировать, поскольку всё внутри "/" сохраняется (имеется в виду, что сценарии загрузки можно изменять, сохраняя при этом сессию обычным способом --- прим. перев.). Единственный скрипт, который не удастся отредактировать напрямую --- это **/initrd/sbin/init** --- скрипт загрузки из начального рамдиска.
 +
 +Продолжение следует... ^_^
  
Печать/экспорт