Библиотека сайта rus-linux.net
Руководство по созданию простой UNIX-подобной ОС
1. Настройка среды разработки
Оригинал: "1. Environment setup"Автор: James Molloy
Дата публикации: 2008
Перевод: Н.Ромоданов
Дата перевода: январь 2012 г.
Нам нужна среда, в которой мы будем проектировать и собирать наше ядро. Везде далее предполагается, что вы пользуетесь системой *nix и инструментарием GNU. Если вы хотите использовать систему windows, вы должны либо воспользоваться пакетом cygwin (который является средой, эмулирующей *nix), либо DJGPP. В случае, если используется windows, файлы make и команды, приведенные в настоящем руководстве, могут не работать.
1.1. Структура директориев
Структура моих директориев следующая:tutorial | +-- src | +-- docs
Все ваши файлы с исходным кодом будут находиться в директории src, а вся ваша документация (вы пишите документацию?) должна быть в директории docs.
1.2. Компиляция
Примеры, приведенные в этом руководстве, должны успешно компилироваться с помощью инструментария GNU (gcc, ld, gas и т.д.). примеры на ассемблере написаны с использованием синтаксиса Intel, который более удобен (мое личное мнение), чем синтаксис, используемый в GNU AS. Чтобы выполнять ассемблирование, вам нужен Расширенный ассемблер.
В этом руководстве не описывается разработка загрузчика. Для загрузки нашего ядра мы будем пользоваться загрузчиком GRUB. Чтобы это делать, нам нужен образ дискеты с предустановленным в нем загрузчиком GRUB. Есть руководства, в которых описывается, как это делать, но, к счастью, я взял стандартный образ, который можно найти здесь. Он должен находиться в вашем директории 'tutorial' (или в главном директории проекта с тем названием, которое вы ему дали).
1.3. Запуск на исполнение
В качестве тестовой системы нет альтернативы чистому аппаратному железу. К сожалению, чистое аппаратное железо не так привлекательно, когда что-то идет не так (но вы, разумеется, собираетесь писать код сразу абсолютно без ошибок, не так ли?). Возьмите эмулятор Bochs. Bochs является эмулятором для платформы x86-64 с открытым исходным кодом. Когда дела пойдут совсем не так, как надо, эмулятор bochs сообщит вам об этом и сохранит состояние процессора в журнальном файле, что чрезвычайно полезно. Кроме того, его можно запустить и перезагрузить гораздо быстрее, чем реальную машину. Мои примеры будут сделаны так, чтобы они хорошо работали под эмулятором bochs.
1.4. Эмулятор Bochs
Для того, чтобы запустить эмулятор bochs, вам нужен конфигурационный файл bochs (bochsrc.txt). Так получилось, что в качестве образца конфигурационного файла можно взять файл, приведенный ниже!
Обратите внимание на то, где находятся файлы bios. Возможно, они используются для переключения между вариантами настройки, и если вы собираете bochs из исходных кодов, то весьма возможно, что их у вас вообще не будет. Поищите их в Google по их названиям, их можно, среди прочего, получить с официального сайта bochs.
megs: 32 romimage: file=/usr/share/bochs/BIOS-bochs-latest, address=0xf0000 vgaromimage: /usr/share/bochs/VGABIOS-elpin-2.40 floppya: 1_44=/dev/loop0, status=inserted boot: a log: bochsout.txt mouse: enabled=0 clock: sync=realtime cpu: ips=500000
В этом файле указывается, что bochs эмулирует машину с оперативной памяти объемом в 32 MB и тактовой частотой, эквивалентной компьютеру PentiumII с тактовой частотой 350MHz. Можно увеличить число инструкций, исполняемых в секунду, но я предпочитаю медленную скорость эмуляции, просто так я могу следить за тем, как обрабатываются тексты большого размера.
1.5. Полезные скрипты
Мы собираемся выполнять некоторые действия очень часто - создавать (компилировать и компоновать) наш проект и переносить получившийся в результате двоичный код ядра в наш образ дискеты
Примечание переводчика: В следующих скриптах и везде далее в исходных кодах примеров строки комментариев переведены с английского языка на русский. Это сделано с целью помочь читателю лучше разобраться с исходными кодами примеров. Но, естественно, что из-за комментариев, написанных на русском языке, при компиляции и сборке ядра почти наверняка возникнут проблемы. Поэтому для того, чтобы избежать подобных проблем, для компиляции и компоновки проекта нужно брать исходные коды примеров с сайта оригинала перевода.
1.5.1. Скрипт Makefile
# Makefile для руководств по сборке ядра - автор James Molloy. # Правила обработки C и C++ указаны как используемые по умолчанию. # Единственное, что нужно изменить, это указать правила обработки # ассемблера, поскольку мы используем nasm вместо GNU as. SOURCES=boot.o CFLAGS= LDFLAGS=-Tlink.ld ASFLAGS=-felf all: $(SOURCES) link clean: » -rm *.o kernel link: » ld $(LDFLAGS) -o kernel $(SOURCES) .s.o: » nasm $(ASFLAGS) $<
С помощью этого файла Makefile все файлы, находящиеся в директории с исходными кодами, будет компилироваться, а затем будут компоноваться вместе в один двоичный файл в формате ELF с названием 'kernel'. Для этого в нем используется скрипт компоновщика 'link.ld':
1.5.2. Скрипт Link.ld
/* Link.ld -- скрипт компоновщика ядра - проследите за тем, чтобы */ /* это выполнялось в правильном месте. */ /* Исходный файл был взят из руководства по разработке ядра Bran's */ /* Kernel Development: http://www.osdever.net/bkerndev/index.php. */ ENTRY(start) SECTIONS { .text 0x100000 : { code = .; _code = .; __code = .; *(.text) . = ALIGN(4096); } .data : { data = .; _data = .; __data = .; *(.data) *(.rodata) . = ALIGN(4096); } .bss : { bss = .; _bss = .; __bss = .; *(.bss) . = ALIGN(4096); } end = .; _end = .; __end = .; }
В этом скрипте загрузчику LD указывается, как настроить наш образ ядра. Во-первых, в нем с помощью символа 'start' загрузчику LD указывается, что наш двоичный файл располагается в самом начале. Затем в нем загрузчику LD сообщается, что секция .text (где находится весь ваш код), которая должна идти первой, должна начинаться с адреса 0x100000 (1 Мб). Следующими должны быть секции .data (инициализированные статические данные) и .bss (неинициализированные статические данные), причем каждая секция должна быть выровнена относительно начала страницы (ALIGN (4096)). Компилятор Linux GCC также добавляет дополнительную секцию данных .rodata, которая используется для инициализированных данных, таких как константы. Для простоты мы их просто помещаем в секцию .data.
1.5.3. Скрипт update_image.sh
Приятный небольшой скрипт, который будет перемещать новое двоичное ядро в файл образа дискеты (предполагается, что вы это делаете в директории /mnt). Примечание: чтобы использовать команду losetup, вам нужно указать путь к директорию /sbin в переменной среды окружения $PATH.
#!/bin/bash sudo losetup /dev/loop0 floppy.img sudo mount /dev/loop0 /mnt sudo cp src/kernel /mnt/kernel sudo umount /dev/loop0 sudo losetup -d /dev/loop0
1.5.4. Скрипт run_bochs.sh
Этот скрипт настройки устройства loopback, запустите на нем эмулятор bochs, а затем отключите это устройство.
#!/bin/bash # run_bochs.sh # правильно монтирует устройство loopback, запускает bochs, а затем демонтирует устройство. sudo /sbin/losetup /dev/loop0 floppy.img sudo bochs -f bochsrc.txt sudo /sbin/losetup -d /dev/loop0
Назад | К началу | Вперед |