Введение

PC-ОС

БП

Дисплей

Координатор

Выбор ОС

Собственно, на самом деле выбор этот для меня был очень прост.

Начнем от простейшего варианта: систему можно написать самому. Задача, стоящая перед аппаратно- програмным комплексом не сильно сложная, процессор мощный (Да, мощный ! ~166*10^6 тактов в секунду. Тетрис просто летает), памяти много (а вы пробовали писать программы на ассемблере ? Сколько времени вы будете писать осмысленный код, который займет хотя бы половину имеющейся в наличии памяти - 16 Мб ?), аппаратура почти вся хорошо и на много раз документирована. Здесь есть две проблемы: 1) документировано все таки не все. Например, звук у меня был на чипе Vortex. К нему доки закрыты. 2) пожалуй, код для декодирования mp3 я напишу, но осваивать для этого доки или чужие исходники - это очень тонкое развлечение. Попытаться адаптировать тот же исходник mpg321 к собственной системе.... В общем: как нибудь в другой раз.

Чуть усложним: ms-dos (ну и прочие: ps-dos, dr-dos, .... freedos ... кто больше ?). Да, под нее есть даже готовые dosamp, mp3-486 - но это продукты без исходных кодов и не склонные к взаимодействию с другими программами - у них только обычный экранный интерфейс. А нам нужна координация, управление с ИК и прочие вкусности. Да и проги эти излишнией универсальностью и корректностью не страдают - не все субформаты mp3 им понятны, не со всеми звуковухами они дружат.

QNX. Ну до кучи приплетем сюда Minuet, v2os, ... э-э-э... где у меня компашка с музеем операционок - я без нее и всех названий -то не упомню. Вот, например, была там *NIX-подобная операционка, но с форматом исполняемых файлов - ms-dos-exe. Да, под ней даже Volcov Commander пытался работать. С переключением виртуальных консолей по Alt-F :). В общем, наверное, среди таких ОС можно найти подходящую, но вот нет по ним соответствующего обзора.

Винда. Под ней подобную конструкцию делали - я встречал упоминание в инете, но без подробностей (winamp + плагины). Но у меня к ней личная неприязнь. Потому что если большинство описаний к другим ОС можно в среднем озаглавить словом "Почему (как устроено) ?", то документация к винде будет начинаться со слова "Как (добиться конкретного результата) ?". Причем темы "Как сделать из винды безмониторный "MP3-плейер"" там не наблюдается, впрочем как и 95% других, интересующих меня тем.

FreeBSD, ну пусть заодно и другие *BSD. Эту систему я использую как десктоп, но вот ранее упомянутый Vortex она не поддерживает. Возможно, помогла бы установка драйверов от 4Front Technologies (по крайней мере именно так я заставил под FreeBSD 4.11 работать Audigy 2), но ...

... есть ведь еще Linux. Т.е. та куча систем, которая использует ядро (ну и всю кучу сопутствутющих драйверов, а заодно и прикладной софт) от компании Линус Торвальдс & единомышленники. Я давно хотел с ней поиграться, но просто поставить и ... что дальше ? Фря работает, все что надо делает. Ну появится еще одна система... Придётся выбирать с чем работать после каждого включения машины :). А тут повод. И Vortex поддерживается.

Почему Zenwalk ? Потому что это ветка широко известной в узких кругах Slackware - версии/дистрибутива Linux, предназначенной для тех, кто еще не докурился до нирваны сборки Linux From Scratch (т.е. буквально - сборки дистрибутива по... ну почти по отдельным файлам), но в то же время считает любые подсказки и помощь от системы и ее инсталятора излишними. Чем, разумеется, экономит дисковое пространство, время... ну и, конечно, наслажается красотой технической простоты. Примерно как математик, сокращающий длинное уравнение.

Конечно, не последнюю роль в выборе сыграло включение Zenwalk в один из недавно пришедших DVD к журналу LinuxFormat. Thank's.

Ядро системы я пересобирал сам, хотя это, в зависимости от мощности машины, может быть необязательно. Список установленных пакетов:

aaa_base-10.1.0-noarch-2
aaa_elflibs-10.1.0-i486-1
alsa-lib-1.0.9-i486-1
alsa-utils-1.0.9a-i486-2
audiofile-0.2.6-i486-1
bash-3.0-i486-2
bin-9.2.0-i486-2
binutils-2.15.92.0.2-i486-3
bzip2-1.0.3-i486-1
ccache-2.4-i486-1
coreutils-5.2.1-i486-1
cxxlibs-5.0.6-i486-1
devs-2.3.1-noarch-22
diffutils-2.8.1-i386-1
e2fsprogs-1.38-i486-2
esound-0.2.36-i486-1m7
etc-5.1-noarch-2m7
findutils-4.1.7-i386-1
gawk-3.1.4-i486-1
gcc-3.3.6-i486-1
gcc-g++-3.3.6-i486-1
gdb-6.3-i486-1
glibc-2.3.5-i486-4
glibc-solibs-2.3.5-i486-4
gmp-4.1.4-i486-2
grep-2.5-i386-2
groff-1.19.1-i486-1
gzip-1.3.3-i386-2
hdparm-6.1-i486-1
kbd-1.12-i486-1m7
kernel-2.6.12.2-i486-2m7
kernel-headers-2.4.31-i386-1
less-382-i486-1
libao-0.8.6-i486-1
libid3tag-0.15.1b-i486-1
libmad-0.15.1b-i486-1
libogg-1.1.2-i486-1
libtool-1.5.14-i486-1
libvorbis-1.1.0-i486-1
lilo-22.7-i486-1m7
man-1.5p-i486-1
man-pages-1.64-noarch-1
mc-4.6.0-i486-msam
mpg321-0.2.10-i486-2
ncurses-5.4-i486-2
openssh-4.1p1-i486-1
openssl-solibs-0.9.7g-i486-1
pkgconfig-0.15.0-i486-1
pkgtools-10.2.0-i486-4m7
procps-3.2.3-i486-1
proftpd-1.2.10-i486-1z21
sed-4.0.9-i486-2
shadow-4.0.3-i486-1m7
sysvinit-2.84-i486-56m7
tar-1.15.1-i486-1m7
tcpip-0.17-i486-34m7
util-linux-2.12p-i486-1

Файловые системы

Сразу объясню фишку на первой странице про два винта: системный и винт с данными. Причина примитивна: инженеры и программисты BIOS'a имевшейся в наличии материнки по указанию сверху вдруг перестали предполагать о грядущем появлении винтов более чем 32 Гб объёма. Т.е. при подключении, например, 40 Гб винта и объявлению его наличия в BIOS setup, BIOS при загрузке просто зависал. Если же наличие не объявлять - винт не сможет быть загрузочным. Поэтому пришлось использовать два винта: с одного стартует ОС (ядро Linux не использует BIOS для работы с винтами, оно находит их само и в дальнейшем общается без посторонней помощи), на другом лежат данные. Как верно сообщают с мест, BIOS можно и перешить. Если есть исправленный вариант.

Первый винт объёмом 200 Мб. Да, такого объема винты тоже были. Были и еще меньше. 5 Мб, например. Но у меня была только двухсотка. Битых блоков нет, работает безотказно, греться умеет плохо, один недостаток - шумит. Поэтому пришлось сделать так, чтобы после загрузки он отключался. На нем стоит Zenwalk.... и больше ничего. Единственный раздел с файловой системой ext2. Она не сильно надежная (в смысле - не журналируемая), но позже поясню, почему это не важно.

Второй винт - 40 Гб, ноутбучный. AAM у него настроен на максимум (Automatic Acoustic Management Tool, я использовал утилиту от Mishail Mavritsin (2:5020/3637.55@fidonet), есть также, например, Victoria), т.е. производительность в жертву тишины. Впрочем он и так шустрый. Греться не умеет, слышно его в работе только если приложить ухо; т.к. используется в качестве флешки, одет в защитный жестяной корпус со всех сторон. Имеется несколько разделов:

1) hda1 или ad0s1 - FreeBSD. Флешка должна быть загружаемой. Заодно это и бекап домашней системы. Для плейера роли не играет, но т.к. сдвигает номера других разделов, здесь упомянуто. Объём - ~2 Гб, тип 165.

2) hda2 или ad0s2 - ext2. Объём - ~7 Мб, тип 131. Этот раздел каждый раз при загрузке плейера переформатируется и затем используется как /tmp.

3) hda3 или ad0s3 - расширенный раздел в терминологии MS, содержит в себе hda5 или ad0s5 - FAT32 с музыкой или еще чем нибудь. Пользовательские данные, в общем. Этот раздел намеренно создан как extended ("логический диск"), т.к. в этом случае win9x ставит его после букв других дисков (при использовании винта на чужих машинах). В плейере он монтируется как /Data и одновременно является домашним каталогом непривелегированного пользователя deka. Объём - ~36 Гб, тип 15.

/etc/rc.d/

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

Итак: после включения машины процессор начинает выпонять код из ROM, который называется BIOS материнской платы. BIOS тестирует процессор, память и прочие компоненты материнской платы, а заодно пытается разыскать другие BIOSы, находящиеся на картах расширения. Для видеокарты это будет видео-BIOS, для сетевой - менеджер удаленной загрузки и т.д. После всех этих действий, если все опрошенные BIOSы вернули управление (т.е. например, не началась удаленная загрузка) BIOS материнской платы начинает изучать нулевые сектора накопителей, которые указаны в BIOS SETUP как загрузочные. Например, нулевой сектор НЖМД. Если там обнаруживается характерная сигнатура, содержимое сектора падает на адрес 0:7C00 и на него передается управление.

Этот сектор содержит таблицу разделов винта и начальный загрузчик. Все это вместе в терминологии IBM называется Master Boot Record (MBR). Начальный загрузчик переносит сам себя куда нибудь подальше от адресов 0:7C00, изучает таблицу разделов, находит раздел, обозначенный как загрузочный, вычитывает с него нулевой сектор (это не нулевой сектор винчестера, а нулевой сектор относительно начала раздела !) опять же в адрес 0:7C00 и, проверив сигнатуру, передает управление туда. До этого места последовательность загрузки одинакова для всех ОС.

Дальше все зависит от операционки. Если речь идет о линуксе, то еще и от загрузчика, который окажется в нулевом секторе раздела. Я использовал lilo. Он действует очень просто: дочитывает кусок себя, затем находит ядро системы и считывает его в память. Ядро изучает аппаратуру (3-7 секунд), затем монтирует корневую файловую систему (какую именно - ему подсказывает lilo), затем запускает процесс /sbin/init.

Теперь внимательнее. Всё, что было до этого регулированию поддается мало, да и смысла что либо менять нет. Ну можно разрешить быстрый тест памяти в BIOS (если BIOS SETUP это умеет), можно запретить "Floppy boot seek", а в качестве устройства загрузки указать "C only" - несколько секунд еще выиграете.

А вот то, что делает /sbin/init настраивать можно и нужно. Во первых, на слабой машине это может ускорить запуск плейера, во вторых, машина будет отзывчивее при настройке и подстройке. Кстати, если вы внимательно читали предыдущий раздел, должны были обратить внимание, что я не стал использовать swap-раздел. Да, 32 Мб RAM системе вполне хватает. Если настроить хорошо. Т.е. просто выкинуть все лишнее.

Дальше я могу слегка соврать, а могу соврать и сильно, т.к. тут больше моих предположений, чем чтения мануалов.

У /sbin/init есть несколько очень важных задач. Одна из них - запуск и убийство разнообразных процессов. Запуск происходит при загрузке init и при смене т.н. уровня исполнения, убийство - перед сменой этого уровня. Т.е. пошла команда на смену уровня - опа, всё что можно было кроме себя убил, затем то, что указано в конфигурации - запустил. Конфигурация храниться в файле /etc/inittab. Читаем ее внимательно, ибо там много комментариев.

Существует несколько уровней. 0 - остановка, 1 - однопользовательский режим, 2 - аналог 3, 3 - многопользовательский режим, 4 - режим с запущенным X-сервером, 5 - аналог 3, 6 - перезагрузка. /etc/inittab описывает, что (имена программ, аргументы) и как (ну, например: нужно ли заного запускать программу если она завершила работу) нужно запустить на очередном уровне исполнения. Сразу после загрузки init переходит в уровень si, при этом выполняется скрипт /etc/rc.d/rc.S. Затем уровень меняется на 1 и выполняется скрипт /etc/rc.d/rc.K, затем уровень 2 - /etc/rc.d/rc.M (кроме того он будет выполнен и на уровнях 3, 4, 5 если произойдет переход в них). Эти строчки в /etc/inittab мы трогать не будем, но запомним. Обратите внимание - initdefault установлен в 3 - т.е. после попадания в этот уровень автоматические переходы по уровням прекращаются.

Теперь найдите строчку вроде c1:1235:respawn:/sbin/agetty 38400 tty1 linux. Она говорит о том, что на 1, 2, 3 и 5 уровнях следует запустить agetty. Эта программа после запуска системы захватывает виртуальные консоли (те, что переключаются комбинацией Alt-Fx) и запрашивает на них логин. В нормальной ситуации введенный пользователем логин передается программе login, которая, в свою очередь, запрашивает пароль пользователя и в случае верного ответа запускает shell пользователя с нужным уровнем привелегий (сама login исполняется еще с правами суперпользователя, но shell уже будет понижен в уровне, если, конечно, зашел не root).

Но нам-то нужен плейер, поэтому запрос логина-пароля ни к чему. Мы пойдем другим путем:

c1:1235:respawn:/sbin/agetty -n -l /sbin/mywrap 38400 tty1 linux
Теперь на первом виртуальном терминале agetty выполнит всю подготовительную работу, но не запросит логин, а просто передаст управление указанной нами программе, которая будет называться /sbin/mywrap. Это небольшой скрипт, к содержимому которого мы вернемся в следующих главах этого детектива. Обратите внимание: если этот скрипт погибнет, /sbin/init будет пытаться перезапустить его, пока не будет изменен уровень выполнения (т.е., например, пока система не уйдет в подготовку к перезагрузке).

Теперь обратимся к директории /etc/rc.d/. Как вы помните, здесь лежат файлы инициализации системы, которые init последовательно выполняет перед тем, как запустить нашу программу. В этих скриптах перечислено много увлекательных действий, но нам нужно их предельно сократить и слегка подправить логику.

Сократить - потому что скрипты делают попытки запустить разнообразные сервисы, вроде апача, mysql'я и прочего. Сервисы, естественно, не запускаются, просто потому что я их не ставил, но время на проверку этого факта уходит. Как и память. Это касается как процесса загрузки, так и подготовки к shut down'у.

Подправить - потому что мы делаем плейер, а не рабочую станцию. А одим из требований было - возможность безболезнено выключить машину в любой момент. Вот тут начинается самое интересное.

Что значит "в любой момент" ? Это значит, что ОС и программы не должны делать таких операций, неожиданное прерывание которых может привести к дальнейшим проблемам с машиной. Где может храниться информация о том, что какая-то операция не была завершена ? Только в памяти. Т.е. на винте. Т.е. в файловой системе. Т.е. мы должны запретить модификацию файловых систем. Если вы раньше работали только с Windows - крепко наморщите лоб. Юниксоидам понятно и так: нужно, чтобы ключевые файловые системы всегда работали в режиме "только чтение".

Вот здесь я столкнулся с некоторыми проблемами. Попробую вспомнить все:

Файлик /etc/mtab - очень любит перезаписываться командой mount. В т.ч. при работе скриптов инициализации. Эта проблема решается просто, хотя и не очевидно: убираем его, а вместо него делаем ссылку: ln -s /proc/mounts /etc/mtab. После этого командам mount и umount нужно запрещать модификацию /etc/mtab (есть для этого ключик -n).

Файлик ld.so.cache создается при инициализации системы командой ldconfig. В нем описаны местоположения различных библиотек. Если вы изменяете что либо в конфигурации софта, нужно просто руками запустить ldconfig при разрешенной записи на /etc, а вот из скриптов инициализации ldconfig выкинуть.

Даже если указать в /etc/fstab монтирование корневой файловой системы в Read Only, это указание, как ни странно, игнорируется. Поэтому в скриптах инициализации мы самым наглым образом добавим явное указание /sbin/mount -n -o remount,ro /. Вообще, запомните эту команду, она пригодится при отладке. Обратная ей команда /sbin/mount -n -o remount,rw / разрешает запись в файловую систему.

proftpd и кое кто еще любит хранить файлы unix-сокетов где нибудь в районе /tmp. /tmp должна быть открыта для записи. Но если она будет открыта, не факт, что после выключения питания, в следующий раз система вообще сможет смонтировать этот раздел. С другой стороны - данные из этого раздела после выключения питания не нужны. Сделаем все быстро и просто: добавим перед mount /tmp изящное mkfs -q /dev/hdc2. Т.е. форматирование раздела при каждой загрузке. В отличие от винды, где то, что называется "форматирование", фактически является заодно и проверкой физики диска, в *nix'ах форматирование - это только запись в раздел пустого корневого каталога, пустой таблицы инодов и прочих системных областей. Поэтому mkfs на 7-и мегабайтном разделе займет доли секунды.

Согласно ТЗ требуется, чтобы плейер мог сохранять номер или имя текущего трека, мог индексировать коллекцию (а индексы надо куда -то записывать, правда ?). Перебираем мозги и под слоем пыли вспоминаем, что вообще говоря, кнопки "закончить работу" в ms-dos не было, а на диски она писала. Просто ее нельзя было выключать не выйдя из програм, которые держали файлы открытыми, и внимательно относиться к индикатору HDD, а также к настройкам программ кеширования записи. Попробуем заставить линуксовое ядро симулировать стиль ms-dos в отношении раздела с данными: для этого строчка монтирования этого раздела будет выглядеть так:

mount -tvfat -n -o noatime,sync,dirsync,uid=deka,gid=users,iocharset=koi8-r -v /dev/hdc5 /Data
Скорость обмена с разделом, конечно, упадет... ну да ладно (deka - это логин непривелегированного пользователя, от имени которого выполняются некоторые операции. Надо бы его создать. users - его группа).

Ну вот, сложные моменты объяснил, простые посмотрите в архиве, где приведены результирующие конфиги - tar /etc/*. Напрямую копировать в свою систему не рекомендую - несовпадение версий, аппаратуры, ... мало ли что вылезет ? Но как образец и отправная точка - в самый раз.

Владимир