Операционная система ЗОСРВ «Нейтрино» > Руководство разработчика > Основные принципы системной разработки > Запуск системы, быстрая активация устройств > Построение встраиваемых систем > Статьи руководства > Примеры компоновки загрузочных образов



Примеры компоновки загрузочных образов

Практики проектирования файлов построения загрузочного образа

В этой статье:

Введение
Общие примеры
Разделяемые библиотеки (.so)
Многократное выполнение программ
Несколько консолей
Запуск других программ на консолях
Перенаправление
/tmp
Готовый пример — минимальная конфигурация
Готовый пример — файловая система флеш-памяти
Готовый пример — дисковая файловая система
Готовый пример — TCP/IP с сетевой файловой системой
Примечания для конкретных процессоров
Указание процессора
Примеры
Указание программы запуска (startup)
Указание последовательного порта

Введение

В этой статье будут рассмотрены несколько типовых файлов построения загрузочного образа, которые можно использовать для создания образов целевых систем с помощью утилиты mkifs. Статья включает в себя две основных части:

В конце статьи находятся разделы, в которых указаны отличия каждой поддерживаемой платформы от x86 и аспекты, требующие особого внимания.

Мы рекомендуем изучать общий раздел этой статьи и раздел, посвященный конкретному процессору, поскольку в общем разделе рассматриваются компоненты, которые применяются почти в каждой системе (например, разделяемые объекты).

Общие примеры

В этом разделе мы рассмотрим примеры файлов построения загрузочного образа, которые применимы к любой платформе (с незначительными изменениями, которые мы отметим). Сначала мы ознакомимся с фрагментами, которые иллюстрируют различные методы, а затем — с несколькими полными файлами построения загрузочного образа. В разделе "Примечания для конкретных процессоров" указаны изменения, которые необходимо вносить для поддержки различных семейств процессоров.

Разделяемые библиотеки (.so)

Сначала необходимо предоставить драйверам доступ к совместно используемым библиотекам. Всем драйверам требуется как минимум стандартная библиотека C (libc.so или системная библиотека). Поскольку поиск совместно используемых библиотек осуществляется в каталоге /proc/boot, достаточно включить их в образ. Для этого имя совместно используемой библиотеки указывается в отдельной строке файла построения загрузочного образа.


Note: Компоновщик среды выполнения должен находиться в файле ldqnx.so.*, однако сейчас он находится в файле libc.so, поэтому мы создадим символьную ссылку на него в менеджере процессов.

Для этого включим в файл построения загрузочного образа следующие строки:

# включение совместно используемой библиотеки C
libc.so
# создание символьной ссылки на нее с именем ldqnx.so.2
[type=link] /usr/lib/ldqnx.so.2=/proc/boot/libc.so

Как определить, какие разделяемые объекты необходимо включить в образ? Существуют несколько способов:

Многократное выполнение программ

Чтобы выполнять программы несколько раз, необходимо присваивать им атрибут [data=copy]. Чтобы применить атрибут ко всем программам, поместите его в отдельную строку перед списком программ. Если этот атрибут задан, сегмент данных программы копируется перед использованием, что предотвращает его перезапись во время первого выполнения программы.

Несколько консолей

В системах с несколькими консолями или последовательными портами можно выполнять командный интерпретатор на каждом из них. Для этого включите в файл построения загрузочного образа следующие строки:

[+script] .script = {
# здесь запускаются все остальные необходимые драйверы
devc-con -e -n4 &
reopen /dev/con1
[+session] esh &
reopen /dev/con2
[+session] esh &
...

В этом коде выполняются следующие действия:

  1. запускается драйвер консоли с параметром -n для создания нескольких (в этом примере — четырех виртуальных) консолей
  2. стандартные потоки ввода, вывода и ошибок последовательно перенаправляются на каждую консоль
  3. на каждой консоли запускается командный интерпретатор

Важно запускать командный интерпретатор в фоновом режиме (указывая символ &) — в противном случае интерпретация сценария приостанавливается до тех пор, пока командный интерпретатор не завершает работу!

Запуск других программ на консолях

В общем случае этот метод позволяет запускать на консолях любые программы (т.е. не только командный интерпретатор).

Чтобы выполнить аналогичное действие на последовательных портах, запустите драйвер devc-ser8250 и перенаправьте стандартные потоки ввода, вывода и ошибок в каждый порт (например, /dev/ser1, /dev/ser2). После перенаправления запустите нужную программу (в фоновом режиме!).

Директива [+session] объявляет программу лидером сеанса (в соответствии со стандартом POSIX) — обычно это не требуется при запуске обычных программ.

Перенаправление

Можно выполнять команду reopen над любым устройством неограниченное количество раз — например, запустить программу на /dev/con1, далее — командный интерпретатор на /dev/con2, а затем — еще одну программу на /dev/con1:

[+script] .script = {
...
reopen /dev/con1
prog1 &
reopen /dev/con2
[+session] esh &
reopen /dev/con1
prog2 &
...

/tmp

Чтобы создать каталог /tmp на диске в ОЗУ, можно включить в файл построения загрузочного образа следующую строку:

[type=link] /tmp = /dev/shmem

В пространстве путевых имен менеджера процессов создается каталог /tmp, который является символьной ссылкой на каталог /dev/shmem. Поскольку объекты общей памяти хранятся в каталоге /dev/shmem, эта команда фактически позволяет создавать файлы на диске в ОЗУ.

Следует иметь в виду, что строка с атрибутом символьной ссылки ([type=link]) должна находиться вне файлов сценария и загрузки, поскольку указывает утилите mkifs, что необходимо создать ссылку, а не "настоящий" файл.

Готовый пример — минимальная конфигурация

В этом конфигурационном файле выполняется минимальный набор действий для запуска командного интерпретатора на первом последовательном порте:

[virtual=ppcbe,srec] .bootstrap = {
startup-rpx-lite -Dsmc1.115200.64000000.16
PATH=/proc/boot procnto-800
}
[+script] .script = {
devc-serppc800 -e -F -c64000000 -b115200 smc1 &
reopen
[+session] PATH=/proc/boot esh &
}
[type=link] /dev/console=/dev/ser1
[type=link] /usr/lib/ldqnx.so.2=/proc/boot/libc.so
libc.so
[data=copy]
devc-serppc800
esh
# перечисление программ, которые требуется запускать
# с помощью командного интерпретатора: echo, ls, pidin и др...
echo
ls
pidin
cat
cp

Готовый пример — файловая система флеш-памяти

Рассмотрим готовый файл построения загрузочного образа, в котором запускается файловая система флеш-памяти:

[virtual=x86,bios +compress] .bootstrap = {
startup-bios
PATH=/proc/boot:/bin procnto
}
[+script] .script = {
devc-con -e -n5 &
reopen /dev/con1
devf-i365sl -r -b3 -m2 -u2 -t4 &
waitfor /fs0p0
[+session] TERM=qansi PATH=/proc/boot:/bin esh &
}
[type=link] /tmp=/dev/shmem
[type=link] /bin=/fs0p0/bin
[type=link] /etc=/fs0p0/etc
libc.so
[type=link] /usr/lib/ldqnx.so.2=/proc/boot/libc.so
libsocket.so
[data=copy]
devf-i365sl
devc-con
esh

В файле .bootstrap, который находится в файле построения загрузочного образа, указаны обычные модули startup-bios и procnto (программа запуска и ядро). Обратите внимание, что переменная окружения PATH указывает не только на каталог /proc/boot, но и на каталог /bin, который создан с помощью атрибута [type=link] и является ссылкой на путь к файловой системе флеш-памяти /fs0p0/bin.

В файле .script мы запустили драйвер консоли с пятью консолями, перенаправили стандартные потоки ввода, вывода и ошибок в консоль /dev/con1 и запустили драйвер файловой системы флеш-памяти devf-i365sl. Рассмотрим его командно-строковые параметры:

-r
Включает восстановление после ошибок для измененных, недействительных экстентов и неполного освобождения памяти.
-b3
Включает освобождение памяти в фоновом режиме с приоритетом 3.
-u2
Задает максимальный уровень обновления файлов и каталогов (2).
-t4
Задает максимальное количество потоков. Увеличение количества потоков увеличивает производительность, если включено освобождение в фоновом режиме (с помощью параметра -b) и имеются несколько доступных микросхем и/или свободных блоков.

Драйвер devf-i365sl автоматически монтирует раздел флеш-памяти как /fs0p0. Обратите внимание на символьные ссылки, которые созданы в менеджере процессов в конце файла построения загрузочного образа:

[type=link] /bin=/fs0p0/bin
[type=link] /etc=/fs0p0/etc

В результате формируются каталоги /bin и /etc, которые ссылаются на файловую систему флеш-памяти.

Готовый пример — дисковая файловая система

В этом примере мы рассмотрим файловую систему для вращающихся накопителей. Обратите внимание на разделяемые библиотеки, которые необходимо включить в образ:

[virtual=x86,bios +compress] .bootstrap = {
startup-bios
PATH=/proc/boot:/bin LD_LIBRARY_PATH=/proc/boot:/lib:/dll procnto
}
[+script] .script = {
pci-bios &
devc-con &
reopen /dev/con1
# драйверы дисков
devb-eide blk cache=2m,automount=hd0t79:/,automount=cd0:/cd &
# ожидание создания каталога bin для выполнения остальных команд
waitfor /x86 10
# несколько стандартных серверов
pipe &
mqueue &
devc-pty &
# запуск основного командного интерпретатора
[+session] esh &
}
# /tmp указывает на область общей памяти
[type=link] /tmp=/dev/shmem
# перенаправление консольных сообщений
[type=link] /dev/console=/dev/ser1
# программам необходимо, чтобы компоновщик среды выполнения (ldqnx.so)
# находился в фиксированном месте
[type=link] /usr/lib/ldqnx.so.2=/proc/boot/libc.so
# для поддержки жестких дисков
[type=link] /usr/lib/libcam.so.2=/proc/boot/libcam.so
# символьные ссылки для bin, dll и lib (файлы в /x86 с devb-eide)
[type=link] /bin=/x86/bin
[type=link] /dll=/x86/lib/dll
[type=link] /lib=/x86/lib
# совместно используемая C-библиотека (которая также содержит компоновщика среды выполнения)
libc.so
# на случай, если кому-то необходимо поддержка вещественных чисел, а в нашем процессоре отсутствует
# математический сопроцессор
fpemu.so.2
# разделяемые библиотеки для доступа к жестким дискам
libcam.so
io-blk.so
# для файловой системы QNX 4
cam-disk.so
fs-qnx4.so
# для файловой системы UDF и шины PCI
cam-cdrom.so
fs-udf.so
pci-bios
# копирование сегментов кода и данных всех нижеперечисленных исполняемых файлов
[data=copy]
# драйвер консоли, командный интерпретатор и др.
esh
devb-eide
devc-con


Note: В этой версии ЗОСРВ «Нейтрино» невозможно использовать эмулятор математического сопроцессора ( fpemu.so) в статически компонуемых программах.

Файл построения загрузочного образа содержит строку с командой запуска драйвера devb-eide:

devb-eide blk cache=2m,automount=hd0t79:/automount=cd0:/cd &

В этой строке указано, что драйвер devb-eide должен запуститься и передать строку, которая начинается с cache= и завершается в конце команды (без амперсанда), библиотеке блочного ввода/вывода ( io-blk.so). Библиотека проверяет переданную командную строку, запускается с 2-мегабайтным кешем (cache=2m), а затем автоматически монтирует раздел hd0t79 (первый раздел файловой системы) под путевым именем /hd и CD-ROM под путевым именем /cd.

После запуска драйвера нам необходимо дождаться, когда он получит доступ к диску, и выполнить операции монтирования:

waitfor /ppcbe/bin

Эта строка ждет создания имени /ppcbe/bin в пространстве путевых имен (мы предполагаем, что в системе имеется форматированный жесткий диск, который содержит корректную файловую систему с копией target-каталога (на который ссылается переменная окружения KPDA_TARGET) в корневом каталоге.

Теперь у нас имеется готовая файловая система со всеми необходимыми программами, которые мы можем запускать (например, сервер pipe).

В списке совместно используемых объектов указаны файлы .so, которые требуются драйверам и файловой системе.

Готовый пример — TCP/IP с сетевой файловой системой

В этом разделе показан пример файла построения загрузочного образа, который запускает драйвер Ethernet, стек TCP/IP и сетевую файловую систему:

[virtual=armle,elf +compress] .bootstrap = {
startup-abc123 -vvv
PATH=/proc/boot procnto
}
[+script] .script = {
devc-ser8250 -e -b9600 0x1d0003f8,0x23 &
reopen
# запуск сервера PCI.
pci-abc123 &
waitfor /dev/pci
# сетевые драйверы и файловые системы
io-pkt-v4 -dtulip-abc123 name=en
if_up -p en0
ifconfig en0 10.0.0.1
fs-nfs3 10.0.0.2:/armle/ / 10.0.0.2:/etc /etc &
# ожидание создания каталога bin для выполнения остальных команд
waitfor /usr/bin
# несколько стандартных серверов
pipe &
mqueue &
devc-pty &
[+session] sh &
}
# /tmp указывает на область общей памяти
[type=link] /tmp=/dev/shmem
# перенаправление консольных сообщений
[type=link] /dev/console=/dev/ser1
# программам необходимо, чтобы компоновщик среды выполнения (ldqnx.so)
# находился в фиксированном месте
[type=link] /usr/lib/ldqnx.so.2=/proc/boot/libc.so
# Совместно используемая C-библиотека (которая также содержит компоновщика среды выполнения)
libc.so
# если кому-то требуется поддержка вещественных чисел...
fpemu.so.2
# для доступа к файлам по сети
devn-tulip-abc123.so
# библиотека сокетов
libsocket.so
[data=copy]
# сетевые программы
devc-ser8250
io-pkt-v4
fs-nfs3


Note: В этой версии ЗОСРВ «Нейтрино» невозможно использовать эмулятор математического сопроцессора ( fpemu.so.2) в статически компонуемых программах.

Вышеуказанный файл построения загрузочного образа очень похож на предыдущий файл сборки для диска; их основное различие заключается в том, что вместо запуска дисковой файловой системы с помощью менеджера devb-eide мы запустили сетевые драйверы с помощью менеджера io-pkt-v4. Параметр -d задает сетевой драйвер, который необходимо загрузить.

После запуска менеджера сети необходимо приостановить интерпретацию файла сценария до тех пор, пока драйверы не станут готовыми к работе. Для этой цели используется команда waitfor /dev/socket — она ожидает окончания инициализации менеджера сети. Затем команда ifconfig en0 10.0.0.1 задает IP-адрес интерфейса.

Далее запускается модуль файловой системы NFS fs-nfs3 с параметрами, которые монтируют файловую систему узла 10.0.0.2 в две точки: KPDA_TARGET — в каталог /, а /etc — в каталог /etc.

Поскольку монтирование файловой системы удаленного узла занимает некоторое время, в файле построения загрузочного образа указывается еще одна команда waitfor, которая ожидает корректного завершения монтирования (мы предполагаем, что в файловой системе удаленного узла имеется каталог ${KPDA_TARGET}/armle/bin; поскольку мы смонтировали каталог KPDA_TARGET в каталог /, команда waitfor фактически ожидает создания каталога armle/bin в каталоге KPDA_TARGET удаленного узла).

Примечания для конкретных процессоров

В этом разделе мы рассмотрим отличия файлов построения загрузочного образа, которые предназначены для конкретных семейств процессоров, от вышеуказанных общих файлов. Поскольку в ЗОСРВ «Нейтрино» почти весь код, специфичный для процессоров и платформ, находится в ядре и startup-*, для перехода с одной платформы на другую (например, с x86 со стандартной BIOS на отладочную плату PowerPC 800) требуется минимум изменений.

Указание процессора

Первое очевидное действие, которое необходимо выполнить — указать в файле построения загрузочного образа процессор, для которого он предназначен. Это несложно — в строке [virtual=...] достаточно заменить значение x86 на armle, mipsbe, ppcbe или e2kle.

Примеры

Процессор Атрибут
ARM (с прямым порядком байт) [virtual=armle,binary]
MIPS (с обратным порядком байт) [virtual=mipsbe,elf]
PPC (с обратным порядком байт) [virtual=ppcbe,openbios]

Указание программы запуска (startup)

Еще одно отличие заключается в том, что startup-* связана не только с семейством процессоров, но и с платой, на которой работает конкретный процессор. Если не используется платформа x86 со стандартной BIOS, следует заменить команду startup-bios на одну из многочисленных штатных модулей startup-*.

Чтобы узнать, какие startup-* поддерживаются на текущий момент, обратитесь к следующим источникам:

Указание последовательного порта

В вышеприведенных примерах поддерживается семейство микросхем последовательных портов 8250. Одни платформы, отличные от x86, также поддерживают семейство 8250, а в других используются собственные микросхемы последовательных портов.

Подробную актуальную о наших драйверах последовательных портов см. в описании драйверов devc-*.




Предыдущий раздел: перейти