Автор: Patrick Mahoney
Дата: .03.2003
Раздел: Низкоуровневое программирование в Linux
Одна из самых больших проблем, с которыми программист сталкивается при первых попытках разработать свою ОС - незнание с чего начать. Многие книги расписывают глубинные теоретические проблемы операционных систем, но я не знаю ни одной, которая бы взяла программиста за руку и лицом к лицу столкнула его с этими проблемами. Именно это я считаю целью этой статьи.
Несколько статей связанные с этой темой появились в недавних выпусках Linux Gazette. Я планирую подойти к проблеме с менее "программистки-ориентированной" стороны, предоставляя читателю только инструменты и советы, в которых он нуждается. Предполагается, что ознакомившись со статьей, заинтересовавшийся читатель сумеет начать придумывать и воплощать свои идеи разработки ОС в программный код, будучи ознакомленным с тем, какую именно информацию ему нужно будет искать.
Вы можете не знать этого, но разработка операционной системы начинается не в начале (!!). Разработка приличного загрузчика - проект сам по себе очень сложный, и я бы не советовал вам начинать разработку с написания загрузчика. Множество очень хороших и надежных загрузчиков свободно доступно (Grub, lilo, ppcboot, etc...). Если вы все таки планируете написать собственный, я советую вам повременить с этим. В этой статье я буду использовать GNU Grub, Grand Unified Bootloader.
Дабы облегчить трудности разработки ОС, вам понадобится:
- Возможность *быстро* тестировать ядро
- Возможность *НЕ* перезагружать компьютер, на котором будет происходить разработка
- Возможность *НЕ* использовать дискеты при тестировании системы
Эта статья познакомит вас с одним из возможных вариантов рзаработки, который соотвествует всем вышестоящим требованиям. Этот вариант состоит из компьютера, на котором будет происходить разработка и "подопытного" компьютера, на котором будет происходить тестирования. Эти компьютеры должны находиться в одной сети.
Как и следовало ожидать, эта машина должна иметь хороший комплект средств разработки: ассемблер, компилятор Си, компоновщик и утилита "Make" - необходимый минимум.
Программа, которая более полезна, чем я когда-то думал - эмулятор. Эта штука позволит вам отлаживать и мгновенно тестировать систему. Тем не менее, эмулятор никогда не заменит живую машину.
Еще вам понадобится сервер TFTP. Он позволит подопытной машине загружать ядро с компьютера разработчика по сети.
Все что ему нужно - сетевая карта и загрузчик, который поддерживает протокол TFTP.
Выбранные мною инструменты:
- gcc 2.95.4Для того, чтобы использовать Bochs, вам понадобится образ диска. Он должен иметь загрузчик и файловую систему. Это можно сделать используя скрипт mkbimage. В качестве TFTP сервера я выбрал atftpd. Это легкий в использовании сервер для linux.
Выбранный загрузчик - GNU Grub 0.92. Важно скомпилировать его с поддержкой tftp для вашей сетевой карты. Обязательно внимательно прочитайте инструкции в файлах netboot и README.netboot. У меня стоит дешевый клон NE2000 ISA и я использовал вот эти команды:
$ ./configure --enable-ne --enable-ne-scan=0x220
$ make
Примечание: сконфигурировать нормальную PnP PCI карту будет проще. Теперь вы можете либо установить образы дисков Grub на MBR машины либо на дискету, с которой она будет грузиться. Я предпочел второй вариант, т.к. мой компьютер используются также и для других целей и я не рискнул играться с жестким диском.
$ cat ./stage1/stage1 ./stage2/stage2 > /dev/fd0
Теперь попробуйте загрузиться с дискеты, чтобы проверить распозналась ли сетевая карта. Вы можете либо сконфигурировать ее вручную либо использовать dhcp сервер (если таковой имеется в сети).
grub> dhcp
Probing... [NE*000]
NE2000 base 0x220, addr 00:C0:A8:4E:5A:76
Address: 192.168.22.14
Netmask: 255.255.255.0
Server: 192.168.22.1
Gateway: 192.168.22.1
Примечание: необязательно каждый раз при загрузке конфигурировать эти параметры. Смотрите документацию GNU Grub и скрипт 'grub-install'.
Все готово для того, чтобы протестировать установку!
Как я указал раньше, я оставил собственно программирование ОС экспертам. Так что для того, чтобы протестировать Grub, я использовал примерное ядро из его поставки, расположенное в директории /docs. Оно собирается из трех файлов: boot.S, kernel.c и multiboot.h. То есть собрать его можно командами:
$ gcc -I. -c ./boot.S
$ gcc -I. -c ./kernel.c
$ ld ./kernel.o ./boot.o -o kernel -Ttext 100000
Вот быстрое и неполное разъяснение: Multiboot - стандарт, который определяет путь передачи информации от загрузчика к загружаемому ядру. boot.S принимает эту информацию, устанавливает стек и вызывает функцию 'cmain'. Эта функция настраивает VGA, читает переданную ей информацию выводит на экран текст и завершается. После этого boot.S получает управление обратно, выводит строку 'Halted.' и входит в бесконечный цикл. Весьма просто? Читателю предлагается самостоятельно исследовать этот код для выяснения деталей
План таков: примонтировать образ диска как loopback устройство, скопировать ядро на него, отмонтировать и запустить Bochs. Конечно, вам понадобиться добавить смещение на начало ФС. Но вы знаете его, не так ли?
# /sbin/losetup -o 32256 /dev/loop1 ./c.img
# /bin/mount -t ext2 /dev/loop1 /mnt/osdev/
# cp /docs/kernel /mnt/osdev
# umount /mnt/osdev/
# /sbin/losetup /dev/loop1 -d
$ bochs
Конечно, ваш Makefile может это автоматизировать. Как только вы окажетесь в Grubпросто наберите:
grub> kernel (hd0,0)/kernel
grub> boot
Сперва установите TFTP сервер, так что клиент сможет получать с него ядро.
# /usr/sbin/atftpd --daemon /home/bono/src/grub-0.92/docs
Запускайте подопытную машину. Сконфигурируйте сеть как показано выше. Затем, укажете IP адрес основного компьютера и местонахождение образа ядра. Примечание: эта информация может быть установлена dhcp сервером. И наконец, запустите процесс загрузки:
(...)
grub> tftpserver 192.168.22.36
Address: 192.168.22.14
Netmask: 255.255.255.0
Server: 192.168.22.36
Gateway: 192.168.22.1
grub> kernel (nd)/kernel
[Multiboot-elf, <0x100000:0x807:0x0>, <0x101808:0x0:0x4018>,
shtab=0x106190, entry=0x100568]
grub> boot
Вы уже достаточно далеко продвинулись и настроены начать разработку собственной ОС? Ищите в интернете, спрашивайте, думайте... Монолитное или микроядро? Сегментация или страничная адресация? ...
Если возможности отладки, предоставляемые эмулятором и функцией printk недостаточны, вы можете использовать последовательный отладчик, который подключается через COM-порт. Это достаточно часто используется при разработке ОС.