Software
26 September 2011

Как начать и не бросить писать ОС

From Sandbox
Очередной велосипедЧитая Хабр в течении последних двух лет, я видел только несколько попыток разработки ОС (если конкретно: от пользователей pehat и iley (отложено на неопределённый срок) и Igor1024 (не заброшено, но пока больше походит на описание работы защищённого режима x86-совместимых процессоров, что бесспорно тоже необходимо знать для написания ОС под x86); и описание готовой системы от alman (правда не с нуля, хотя в этом нет ничего плохого, может даже наоборот)). Мне почему-то думается, что почти все системные (да и часть прикладных) программисты хотя бы раз, но задумывались о написании собственной операционной системы. В связи с чем, 3 ОС от многочисленного сообщества данного ресурса кажется смешным числом. Видимо, большинство задумывающихся о собственной ОС так никуда дальше идеи и не идёт, малая часть останавливается после написания загрузчика, немногие пишут куски ядра, и только безнадёжно упёртые создают что-то отдалённо напоминающее ОС (если сравнивать с чем-то вроде Windows/Linux). Причин для этого можно найти много, но главной на мой взгляд является то, что люди бросают разработку (некоторые даже не успев начать) из-за небольшого количества описаний самого процесса написания и отладки ОС, который довольно сильно отличается от того, что происходит при разработке прикладного ПО.

Этой небольшой заметкой хотелось бы показать, что, если правильно начать, то в разработке собственной ОС нету ничего особо сложного. Под катом находится краткое и довольно общее руководство к действию по написанию ОС с нуля.


Как не надо начинать

Don't do thatПросьба не воспринимать следующий ниже текст как явную критику чьих-то статей или руководств по написанию ОС. Просто слишком часто в подобных статьях под громкими заголовками акцент делается на реализации какой-то минимальной заготовки, а подаётся она как прототип ядра. На самом деле следует задумываться о структуре ядра и взаимодействии частей ОС в целом, а тот прототип рассматривать как стандартное «Hello, World!»-приложение в мире прикладного ПО. В качестве небольшого оправдания этих замечаний, следует сказать, что ниже есть подраздел «Hello, World!», которому в данном случае уделено ровно столько внимания сколько нужно, и не больше.

Не надо писать загрузчик. Умные люди придумали Multiboot Specification, реализовали и подробно описали, что это такое и как его использовать. Не хочу повторяться, просто скажу, что это работает, облегчает жизнь, и его надо применять. Спецификацию, кстати, лучше прочесть полностью, она небольшая и даже содержит примеры.

Не надо писать ОС полностью на ассемблере. Это не так чтобы плохо, скорее наоборот — быстрые и маленькие программы всегда будут в почёте. Просто так как этот язык требует значительно больших усилий на разработку, то использование ассемблера приведёт только к уменьшению энтузиазма и, как следствие, к забрасыванию исходников ОС в долгий ящик.

Не надо загружать кастомный шрифт в видео память и выводить что-либо на русском. Толку от этого никакого. Гораздо проще и универсальнее использовать английский, а изменение шрифта оставить на потом, загружая его с жёсткого диска через драйвер файловой системы (заодно будет дополнительный стимул сделать больше, чем просто начать).

Подготовка

preparationsДля начала как всегда следует ознакомиться с общей теорией, дабы иметь какие-то представления о предстоящем объёме работ. Хорошими источниками по рассматриваемому вопросу являются книги Э. Таненбаума, которые уже упоминались в других статьях о написании ОС на Хабре. Также есть статьи с описанием существующих систем, и есть различные руководства/рассылки/статьи/примеры/сайты с уклоном в разработку ОС, ссылки на часть из которых приведены в конце статьи.

После начального ликбеза необходимо определиться с главными вопросами:
  • целевая архитектура — x86 (real/protected/long mode), PowerPC, ARM, ...
  • архитектура ядра/ОС — монолит, модульный монолит, микроядро, экзоядро, разные гибриды
  • язык и его компилятор — C, C++, ...
  • формат файла ядра — elf, a.out, coff, binary, ...
  • среда разработки (да, это тоже играет не последнюю роль) — IDE, vim, emacs, ...

Далее следует углублять знания согласно выбранному и по следующим направлениям:
  • видео память и работа с ней — вывод в качестве доказательства работы необходим с самого начала
  • HAL (Hardware Abstraction layer) — даже если поддержка нескольких аппаратных архитектур и не планируется грамотное отделение самых низкоуровневых частей ядра от реализации таких абстрактных вещей как процессы, семафоры и так далее лишним не будет
  • управление памятью — физической и виртуальной
  • управление исполнением — процессы и потоки, их планирование
  • управление устройствами — драйвера
  • виртуальные файловые системы — для обеспечения единого интерфейса к содержимому различных ФС
  • API (Application Programming Interface) — как именно приложения будут обращаться к ядру
  • IPC (Interprocess Communication) — рано или поздно процессам придется взаимодействовать

Инструменты

toolsУчитывая выбранные язык и средства разработки следует подобрать такой набор утилит и их настроек, которые в будущем позволят путём написания скриптов, максимально облегчить и ускорить сборку, подготовку образа и запуск виртуальной машины с проектом. Остановимся немного детальнее на каждом из этих пунктов:
  • для сборки подойдут любые стандартные средства, как то make, cmake,… Тут в ход могут пойти скрипты для линкера и (специально написанные) утилиты для добавления Multiboot-заголовка, контрольных сумм или для каких-либо других целей.
  • под подготовкой образа имеется ввиду его монтирование и копирование файлов. Соответственно, формат файла образа надо подбирать так, чтобы его поддерживала как утилита монтирования/копирования, так и виртуальная машина. Естественно, никто не запрещает совершать действия из этого пункта либо как финальную часть сборки, либо как подготовку к запуску эмулятора. Всё зависит от конкретных средств и выбранных вариантов их использования.
  • запуск виртуальной машины труда не представляет, но нужно не забыть сначала отмонтировать образ (отмонтирование в этом пункте, так как до запуска виртуальной машины реального смысла в этой операции нет). Также не лишним будет скрипт для запуска эмулятора в отладочном режиме (если таковой имеется).

Hello, World!

Hello, World!Если все предыдущие шаги выполнены, следует написать минимальную программу, которая будет загружаться как ядро и выводить что-нибудь на экран. В случае обнаружения неудобств или недостатков выбранных средств, необходимо их (недостатки) устранить, ну или, в худшем случае, принять как данность.

На данном шаге необходимо проверить как можно больше возможностей средств разработки, которые планируется использовать в будущем. Например, загрузку модулей в GRUB или использование в виртуальной машине физического диска/раздела/флешки вместо образа.

После того как этот этап прошёл успешно, начинается настоящая разработка.

Обеспечение run-time поддержки

runtimeТак как предлагается писать на языках высокого уровня, следует позаботиться об обеспечении поддержки части средств языка, которые обычно реализуются авторами пакета компилятора. Например для C++, сюда относятся:
  • функция для динамического выделения блока данных на стеке
  • работа с heap
  • функция копирования блока данных (memcpy)
  • функция-точка входа в программу
  • вызовы конструкторов и деструкторов глобальных объектов
  • ряд функций для работы с исключениями
  • стаб для нереализованных чисто-виртуальных функций
  • ...

При написании «Hello, World!» отсутствие этих функций может никак не дать о себе знать, но по мере добавления кода, линкер начнёт жаловаться на неудовлетворённые зависимости.

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

Отладка

debuggingНе смотрите, что об отладке говорится ближе к концу статьи. На самом деле это очень серьёзный и непростой вопрос в разработке ОС, так как обычные средства тут неприменимы (за некоторым исключением).

Можно посоветовать следующее:
  • само собой разумеющееся, отладочный вывод
  • assert с немедленным выходом в «отладчик» (см. следующий пункт)
  • некоторое подобие консольного отладчика
  • проверить не позволяет ли эмулятор подключать отладчик, таблицы символов или ещё что-нибудь

Без встроенного в ядро отладчика поиск ошибок имеет вполне реальный шанс превратится в кошмар. Так что от его написания на некотором этапе разработки просто никуда не деться. А раз это неизбежно, то лучше начать его писать заранее и таким образом значительно облегчить себе разработку и сэкономить довольно много времени. Важно суметь реализовать отладчик независимым от ядра образом, чтобы отладка минимальным образом влияла на нормальную работу системы. Вот несколько типов команд, которые могут быть полезны:
  • часть стандартных отладочных операций: точки останова, стек вызовов, вывод значений, печать дампа, ...
  • команды вывода различной полезной информации, вроде очереди исполнения планировщика или различной статистики (она не так бесполезно как может показаться сначала)
  • команды проверки непротиворечивости состояния различных структур: списков свободной/занятой памяти, heap или очереди сообщений

Развитие

develДальше необходимо написать и отладить основные элементы ОС, которые в данный момент должны обеспечить её стабильную работу, а в будущем — лёгкую расширяемость и гибкость. Кроме менеджеров памяти/процессов/(чего-нибудь ещё) очень важным является интерфейс драйверов и файловых систем. К их проектированию следует подходить с особой тщательностью, учитывая всё разнообразие типов устройств/ФС. Со временем их конечно можно будет поменять, но это очень болезненный и подверженный ошибкам процесс (а отладка ядра — занятие не из лёгких), поэтому просто запомните — минимум десять раз подумайте над этими интерфейсами прежде чем возьмётесь за их реализацию.

Подобие SDK

SDKПо мере развития проекта в нём должны добавляться новые драйвера и программы. Скорее всего уже на втором драйвере (возможно определённого типа)/программе будут заметны некоторые общие черты (структура каталогов, файлы управления сборкой, спецификация зависимостей между модулями, повторяющийся код в main или в обработчиках системных запросов (например если драйвера сами проверяют их совместимость с устройством)). Если так и есть, то это признак необходимости разработки шаблонов для различного типа программ под вашу ОС.

Необходимости в документации, описывающей процесс написания того или другого типа программы, нет. Но сделать заготовку из типовых элементов стоит. Это не только упростит добавление программ (что можно делать и копированием существующих программ с их последующим изменением, но это потребует больше времени), но также позволит легче их обновлять при изменениях в интерфейсах, форматах или чем-то ещё. Понятно, что таких изменений в идеале быть не должно, но так как разработка ОС — вещь нетипичная, то есть достаточно много мест для потенциально неверных решений. А вот понимание ошибочности принятых решений как всегда придёт через некоторое время после их внедрения.

Дальнейшие действия

continueЕсли кратко, то: читать про операционные системы (и в первую очередь именно про их устройство), развивать свою систему (темпы на самом деле не важны, главное — не прекращать совсем и возвращаться к проекту время от времени с новыми силами и идеями) и естественно исправлять в ней ошибки (для нахождения которых надо иногда запускать систему и «играться» с ней). Со временем процесс разработки будет становиться всё легче и легче, ошибки будут встречаться реже, а вы будете зачислены в список «безнадёжно упёртых», тех немногих, которые несмотря на некоторую абсурдность идеи разработки собственной ОС, всё же сделали это.

Полезные ссылки

На Хабре:
Пишем свою ОС: Выпуск 1
Пишем свою ОС: Выпуск 2
Продолжаем написание операционок. Шаг за шагом
Что такое Protected Mode и с чем его едят
Учим систему страничной адресации и обработке прерываний
Начинаем разговор о многозадачности
Память и задачи

Другие источники с большим количеством информации по разработке ОС:
wasm.ru
sysbin.com
wiki на osdev.org
iakovlev.org
Bona Fide OS

+109
46.9k 220
Comments 55
Top of the day