Ошибка: Failed to parse the Currency Converter XML document.
$19 825.24
|
Ошибка: Failed to parse the Currency Converter XML document.
$27 140.08
|
Ошибка: Failed to parse the Currency Converter XML document.
$2 010.62
|
FreeBSD под эмулятором Bochs
В этой статье описывается мой опыт по сборке урезанного варианта FreeBSD «с нуля» и запуска ее под эмулятором Bochs. Основываясь на статье Йенса Швайкхардта (Jens Schweikhardt) «FreeBSD From Scratch», здесь я развиваю эту идею дальше, путем использования виртуального диска из файла в качестве установочной директории и образа диска для запуска системы под эмулятором Bochs.
Примечание: Описанный в этой статье порядок действий опробован мною на FreeBSD 5.3-RELEASE и должен быть применим ко всем версиям FreeBSD 5.X (-CURRENT и -STABLE). Для FreeBSD 4.X необходимо вместо драйвера md(4) использовать vn(4).
Введение
Будучи пользователем FreeBSD на протяжении двух лет, меня очень интересует код этой системы, хотя его не так легко понять. Я знаю, что намного легче узнать, как работает система, если наблюдать ее «за работой» и сопоставлять это с ее кодом, чем просто просматривая исходники системы. Так как я не мог проводит эксперименты с рабочей системой и не мог себе позволить приобретение второго компьютера, разумным выходом стало использование эмулятора Bochs (попросту говоря, Bochs -- это программа, которая эмулирует поведение компьютера (в настоящее время поддерживается только x86-архитектура), позволяя запускать различные операционные системы внутри уже работающей ОС). Хотя в этой статье описывается удачный запуск мною FreeBSD под эмулятором Bochs, не стоит рассматривать ее как руководство. Это всего лишь рассказ об успешном эксперименте начинающего FreeBSD«шника.
Мой эксперимент ставит целью построение системы из исходных кодов и ее установку на виртуальный диск, который используется в качестве образа жесткого диска для эмулятора Bochs. Таким образом, весь процесс состоит из двух частей. Сначала создается и размечается виртуальный диск (разделы, файловые системы и т.д.), затем компилируется система и устанавливается на подготовленный виртуальный диск.
Подразумевается, что вы обладаете общими знаниями о FreeBSD и умеете работать в консоли. Некоторые команды потребуют полномочий суперпользователя, поэтому вам потребуется использовать su (убедитесь сначала, что текущий пользователь входит в группу wheel) либо sudo (опять же, убедитесь в наличии полномочий, установленных в файле sudoers).
Что нам понадобится
Рабочая FreeBSD 5.X. Пользователи FreeBSD 4.X должны будут подправить основной скрипт и приведенные ниже команды с учетом необходимости использования vn(4) вместо md(4).
Исходники системы в полном объеме (/usr/src).
Эмулятор Bochs. Если он еще не установлен, то в командной строке выполните $ cd /usr/ports/emulators/bochs/ && make install
Примерное представление о шелл-скриптах.
Создаем отдельную директорию для нашего эксперимента
Раз уж наш эксперимент достаточно сложный и подразумевает работу с несколькими файлами, будет лучше, если вы отведете для него отдельную директорию, чтобы необходимые файлы не затерялись среди других ваших документов.
$ mkdir -p /my/home/vfbsd
$ cd /my/home/vfbsd
Настройка эмулятора Bochs
Конфигурационный файл Bochs должен содержать параметры эмулируемого компьютера, расположение файлов с образами памяти и дисков, а также другую информацию (подробнее в bochsrc(5)). Для нашего эксперимента создадим в подготовленной директории файл bochs.rc и добавим в него следующие строки:
#### my bochs conf ####
boot: disk
megs: 32
romimage: file=/usr/local/share/bochs/BIOS-bochs-latest, address=0xf0000
vgaromimage: /usr/local/share/bochs/VGABIOS-lgpl-latest
Примечание: Параметр boot определяет загрузочное устройство; megs -- объем оперативной памяти, доступный внутри эмулятора; romimage и vgaromimage -- расположение файлов с образами BIOS и видеопамяти (эти файлы поставляются вместе с эмулятором Bochs и по умолчанию устанавливаются в /usr/local/share/bochs).
Настройка параметров виртуального диска и сборка FreeBSD из исходных кодов
Создадим файл для образа диска (с названием hd.image и размером 512Mб), запустив утилиту bximage без параметров (интерактивная программа, являющаяся часть пакета Bochs) и ответив на простые вопросы.
Совсем не обязательно выделять под файл образа диска именно 512 Мб, но именно исходя из этого значения в данной статье рассчитываются все необходимые параметры. После того, как программа создаст файл, она выдаст рассчитанные параметры эмулируемого диска и строку, которую нужно будет добавить в конфигурационный файл bochs.rc. В нашем случае это:
ata0-master: type=disk, path=«hd.image», mode=flat, cylinders=1040, heads=16, spt=63
Добавляем эту строку в файл bochs.rc.
Все следующие действия выполняются одним скриптом. Поместите его в созданную директорию. Перед тем, как запустить его, убедитесь, что вы понимаете, как он работает. Убедитесь также, что все переменные заданы правильно. Запустите скрипт.
Примечание: Вы должны уметь работать с mergemaster. Это достаточно простая программа, однако стоит все-таки прочитать маны.
Собственно, сам скрипт:
#!/bin/sh -x
#
# vfbsd_setup.sh http://sig9.com/articles/freebsd-on-bochs
#
# Copyright (c) 2004, Vivek Mohan (http://sig9.com/)
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# «AS IS» AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# !! This shell script file sets up the virtual FreeBSD system from
# !! scratch.
# !! Убедитесь в том, что переменные заданы правильно.
SETUPDIR=`pwd`
#---------------------------------------------------------------------#
# Переменная Описание
# ========== ===========
#
# HDIMAGE Файл, содержащий образ виртуального диска
# SRCDIR Расположение исходников системы
# KERNCONF Конфигурационный файл ядра
# LABELTMP временный файл для работы bsdlabel
# FSTABTMP временный файл fstab
# MDUNUM Порядковый номер виртуального диска
# VDMNT Точка монтирования виртаульного диска
# BUILDDEFINES Опции для команд make buildworld и make installworld
#---------------------------------------------------------------------#
HDIMAGE=«hd.image»
SRCDIR=/usr/src/
KERNCONF=«GENERIC»
MDUNUM=4
LABELTMP=«bsdlabel.tmp»
FSTABTMP=«fstab.tmp»
VDMNT=${SETUPDIR}/mnt
TEMPROOT=«/var/tmp/temproot.vfbsd»
BUILDDEFINES=«-DNOCRYPT -DNOMAN -DNOPROFILE -DNOSECURE »
«-DNOPROFILE -DNOGAMES -DNOINFO -DNOLIBC_R -DNO_FORTRAN »
«-DNOCLEAN»
#---------------------------------------------------------------------#
# Для того, чтобы стало возможным использовать виртуальный диск, он
# должен быть размечен также как и при обычно установке FreeBSD.
# Созданный на основе нижеследующих данных файл с названием,
# определенным в переменной LABELTMP будет обработан утилитой
# bsdlabel(8). В нашем случае мы создаем 5 разделов, как и при обычной
# установке системы -- /, /var, /tmp, /usr и swap с указанными
# размерами. Подробности см. в мане bsdlabel(8).
#---------------------------------------------------------------------#
cat > ${LABELTMP} << EOLABEL
#--------------------------------BSDLABEL-----------------------------#
8 partitions:
# size offset fstype [fsize bsize bps/cpg] #
# ==== ====== ====== ===================== #
a: 128M 0 4.2BSD # /
b: 20M * swap # swap
c: * * unused 0 0 #
e: 50M * 4.2BSD # /var
f: 50M * 4.2BSD # /tmp
g: * * 4.2BSD # /usr
#---------------------------------------------------------------------#
EOLABEL
cat > ${FSTABTMP} < #--------------------------------FSTAB--------------------------------#
# Device Mountpoint FStype Options Dump Pass
# ========= ========== ====== ======= ==== ====
/dev/ad0a / ufs rw 0 0
/dev/ad0b none swap sw 0 0
/dev/ad0e /var ufs rw 0 2
/dev/ad0f /tmp ufs rw 0 2
/dev/ad0g /usr ufs rw 0 2
pros /proc procfs rw 0 0
#---------------------------------------------------------------------#
EOFSTAB
DESTDIR=${VDMNT}
MD=md${MDUNUM}
MD_SLICE=${MD}
MD_ROOT=${MD_SLICE}a
MD_VAR=${MD_SLICE}e
MD_TMP=${MD_SLICE}f
MD_USR=${MD_SLICE}g
MD_SWAP=${MD_SLICE}b
#---------------------------------------------------------------------#
# Функция do_attach_vdisk() Подключает образ диска из файла, с
# названием, определенным в переменной HDIMAGE, в качестве виртуального
# диска «/dev/${MD}», с которым система сможет работать также как и с
# обычным жестким диском. Подробнее о виртуальных дисках смотрите маны
# md(4) и mdconfig(8).
#---------------------------------------------------------------------#
do_attach_vdisk() {
# Подключает образ диска из файла как виртуальный диск
mdconfig -a -t vnode -f ${HDIMAGE} -u ${MDUNUM}
}
#---------------------------------------------------------------------#
# do_deatach_vdisk() отключает виртуальный диск.
#---------------------------------------------------------------------#
do_detach_vdisk() {
# Отключает виртуальный диск
mdconfig -d -u ${MDUNUM}
}
#---------------------------------------------------------------------#
# do_setup_vdisk() Разметка и настройка параметров виртуального
# диска.
#---------------------------------------------------------------------#
do_setup_vdisk() {
# разметка и запись загрузочного сектора
bsdlabel -B -R /dev/${MD} ${LABELTMP}
# создание файловых систем
newfs /dev/${MD_ROOT}
newfs /dev/${MD_TMP}
newfs /dev/${MD_VAR}
newfs /dev/${MD_USR}
# включение механизма Soft Updates
tunefs -n enable /dev/${MD_ROOT}
tunefs -n enable /dev/${MD_TMP}
tunefs -n enable /dev/${MD_VAR}
tunefs -n enable /dev/${MD_USR}
# создание точки монтирования для виртуального диска и моитирование
mkdir -p ${VDMNT}
mount -o noatime /dev/${MD_ROOT} ${VDMNT}
# создание точек монтирования
mkdir -m 0755 -p ${VDMNT}/var
mkdir -m 0755 -p ${VDMNT}/tmp
mkdir -m 0755 -p ${VDMNT}/usr
# unmount and unload virtual disk device
umount /dev/${MD_ROOT}
}
#---------------------------------------------------------------------#
# do_build() сборка системы и ядра из исходников
#---------------------------------------------------------------------#
do_build() {
# make kernel and world
cd ${SRCDIR}
make buildkernel KERNCONF=${KERNCONF}
make buildworld ${BUILDDEFINES}
cd ${SETUPDIR}
}
#---------------------------------------------------------------------#
# do_install() установка собранной системы и ядра
#---------------------------------------------------------------------#
do_install() {
# mount
mount -o noatime /dev/${MD_ROOT} ${VDMNT}
mount /dev/${MD_TMP} ${VDMNT}/tmp
mount /dev/${MD_VAR} ${VDMNT}/var
mount /dev/${MD_USR} ${VDMNT}/usr
# make distribution directories
cd ${SRCDIR}/etc
make distrib-dirs DESTDIR=${DESTDIR}
# run merge master
mkdir -p ${TEMPROOT}
mergemaster -i -m ${SRCDIR}/etc -t ${TEMPROOT} -D ${DESTDIR}
# install world
cd ${SRCDIR}
make installworld DESTDIR=${DESTDIR} ${BUILDDEFINES}
# copy system files
cp ${SETUPDIR}/${FSTABTMP} ${DESTDIR}/etc/fstab
cp /etc/localtime ${DESTDIR}/etc/localtime
cp ${SRCDIR}/sys/boot/forth/loader.conf ${DESTDIR}/boot/defaults
cp ${SRCDIR}/sys/i386/conf/GENERIC.hints ${DESTDIR}/boot/device.hints
# copied shamelessly from «FreeBSD From Scratch»
cd ${TEMPROOT}
find . -type f | sed »s,^./,,' |
while read f; do
if test -r ${DESTDIR}/${f}; then
echo «${DESTDIR}/${f} already exists; not copied»
else
echo «Creating empty ${DESTDIR}/${f}»
cp -p ${f} ${DESTDIR}/${f}
fi
done
chflags -R 0 ${TEMPROOT}
rm -rf ${TEMPROOT}
# install kernel
cd ${SRCDIR}
make installkernel DESTDIR=${DESTDIR} KERNCONF=${KERNCONF}
# unmount and unload virtual disk device
umount /dev/${MD_TMP}
umount /dev/${MD_VAR}
umount /dev/${MD_USR}
umount /dev/${MD_ROOT}
}
#---------------------------------------------------------------------#
# do_clean_up() удаление двух временных файлов
#---------------------------------------------------------------------#
do_clean_up() {
# remove temp files
rm -f ${FSTABTMP}
rm -f ${LABELTMP}
}
#---------------------------------------------------------------------#
# Установка последовательности выполнение всех шагов
#---------------------------------------------------------------------#
vfbsd_setup() {
do_attach_vdisk
do_setup_vdisk
do_build
do_install
do_clean_up
do_detach_vdisk
}
#---------------------------------------------------------------------#
# Собственно сам запуск последовательности команд сборки и установки
# А также создание лога всего процесса
#---------------------------------------------------------------------#
vfbsd_setup 2>&1 | tee vfbsd_setup.log
Эмуляция
Если скрипт отработал без ошибок, запускаем эмулятор:
$ bochs -q -f bochs.rc
Если вы увидите, что FreeBSD загружается, мои поздравления. Этот скрипт не был тщательно протестирован, поэтому возможны некоторые глюки при работе.
Копирование файлов между двумя операционными системами
Во время работы в гостевой системе может возникнуть необходимость копирования файлов с виртуального диска или на него. Для этого нужно подключить виртуальный диск, и примонтировать его как показано ниже:
$ mdconfig -a -t vnode -f hd.image -u 4
$ mount /dev/md4 ./mnt
Теперь можно копировать файлы. Чтобы отмонтировать и отключить виртуальный диск, введите из консоли:
$ umount /dev/md4
$ mdconfig -d -u 4
Примечание:
Потратив целый день на то, чтобы на практике проверить все написанное в этой статье, я могу сказать, что, как мне показалось, намного проще для всяких экспериментов завести второй экземпляр системы на диске. Потому что скорость работы системы в эмуляторе просто никакая. К сожалению, автор не приводит никаких временных ориентиров, но у меня система загружается 10 минут (и это на P4-2400). Для загрузки в однопользовательском режиме требуется 1.5 минуты. Эмулятор собран с параметрами по умолчанию. Я никогда не работал с другими эмуляторами, поэтому не могу сравнить скорость работы.
С другой стороны, даже если особенного практического значения у статьи нет, есть много отдельных полезных моментов. Интересен процесс создания и разметки образа диска, монтирования разделов виртуального диска, сам скрипт тоже достаточно хорошо структурирован и оформлен.
Но у меня есть некоторые конкретные замечания по скрипту:
1. Я совершенно не согласен с использованием в скрипте переменных KERNCONF и BUILDDEFINES. Намного правильнее использовать подход, применяемый в FREESBIE c переопределением месторасположения make.conf на время сборки системы. В рабочем каталоге создается файл make.conf с необходимыми для конкретной сборки параметрами. Например, если вы установили bochs без указания типа эмулируемого процессора, по умолчанию подразумевается i586 aka Pentium. Поэтому придется явно указать в make.conf CPUTYPE?=i586. В make.conf помещаем наименование конфигурационного файла ядра KERNCONF=имя_файла. Все, что не должно собираться в процессе make buildworld, также проще перечислить в make.conf (подробности в /usr/share/examples/etс/make.conf).
А в основном скрипте нужно просто добавить строку:
export __MAKE_CONF=${SETUPDIR}/make.conf
2. Вместо того, чтобы использовать GENERIC, лучше создать отдельный конфиг ядра. В него можно добавить строку
options ROOTDEVNAME=«ufs:ad0a»
чтобы при каждой загрузке не писать вручную.
3. Функция do_clean_up() не удаляет временные файлы, потому что во время исполнения скрипта текущий каталог постоянно меняется и не возвращается в $SETUPDIR. Поэтому первой строкой функции do_clean_up() должна быть cd ${SETUPDIR}
4. Честно говоря, я совсем не понял, зачем понадобилось использовать mergemaster и кусок кода с find и while. Скрипт каждый раз заново создает образ диска. Что там можно сравнивать в etc для меня осталось загадкой. Поэтому сразу после make distrib-dirs DESTDIR=${DESTDIR} я добавил make distribution DESTDIR=${DESTDIR}, а все, что не нужно, удалил.
И еще некоторые мелочи:
5. В SETUPDIR=`pwd` лучше наименование созданного рабочего каталога явно указать. Так спокойнее.
6. В SRCDIR=/usr/src/ завершающий слэш лучше убрать. Хотя все работает и с ним.