Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
iakovlev.org
Writing a Kernel in C
by Tim Robinson,

Introduction

Написание собственной ОС может длиться недели и месяцы . Но начинать можно , не имея даже особо специфических навыков в С-программировании.


The C Programming Language
Первоначально язык C разрабатывался как низкоуровневый язык . Компиляция С-программы мало отличается от кода , написанного на ассемблере , в том смысле , что си-шный код в конечном итоге транслируется во все тот же ассемблер .
Tools
Существуют 2 главных компонента , транслирующих С-код в машинный - компилятор и линкер . БОльшую работу выполняет компилятор . Есть компиляторы , которые генерят непосредственно исполняемые файлы , но как правило они вызывают линкер неявно.
Линкер обьединяет все обьекты и настраивает ссылочные связи между ними . Линкер позволяет писать код внутри одного проекта на нескольких языках .
Для написания ОС в максимальной степени подходят GNU gcc и ld linker, потому что:
*Они free и open-source

*ld поддерживает любой исполняемый формат

*gcc поддерживается практически на всех известных процах


GNU для различных операционных систем : MS-DOS - DJGPP, Windows - Cygwin. GCC по умолчанию входит во все линуксовые дистрибутивы .

Различные гну-шные тулзы полезны при разработке ОС : пакет binutils включает утилиту objdump , позволяющую исследовать внуренности исполняемых файлов и дизассемблировать их .
Наиболее популярными форматами сейчас являются юниксовый ELF и виндовый PE , поскольку они поддерживаются большинством линкеров . ELF попроще , PE помощнее . Оба хорошо документированы . Есть еще один бинарный формат - COFF , который более специфичен . В качестве альтернативы можно для ядер использовать flat binary format - то бишь отсутствие всякого формата . Ld генерит т.н. raw code , примером которого может служить MS-DOS-кий .COM format.

Недостатком всех основных компиляторов является то , что по умолчанию используется flat 32-битное адресное пространство . Поскольку они не используют far-указатели (48-bit seg16:ofs32) , это усложняет написание кода . Watcom кстати до сих пор обещает написать компилятор OpenWatcom , который теоретически должен поддерживать дальние указатели для 32-bit protected mode.

Есть еще несколько замечаний по поводу работы gcc и ld . Например , gcc похоже ложит символьные строки , используемые внутри функций , выше самих функций . Рассмотрим пример :
int main(void)
{
char *str = "Hello, world", *ch;
unsigned short *vidmem = (unsigned short*) 0xb8000;
unsigned i;

for (ch = str, i = 0; *ch; ch++, i++)
vidmem[i] = (unsigned char) *ch | 0x0700;
for (;;)
;
}


Код должен вывести строку “Hello, world” в видео-память . После компиляции строка окажется выше функции main , и если это залинковать с flat binary format и запустить, то ничего путного не выйдет . Победить это можно так :
* Написать функцию , которая будет вызывать main() и затем halt. В стартовой функции не должно быть символьных строк .

*Использовать опцию gcc -fwritable-strings. Строки будут выведены в data-сегмент .

В обычном мире пользовательских программ роль функции , которая вызывает функцию main() , играет crt0 .


Run-Time Library
Основную часть в написании собственной ОС займет переписывание run-time library, которая еще известна как libc. RTL уже является частью компилятора . Каждый вендор предлагает использовать различные RTL внутри одной OS: Microsoft Visual C++ предлагает различные библиотеки для различных вариантов debug/multi-threaded/DLL, MS-DOS как известно предлагают 6 различных моделей памяти .

Но для начала надо будет определиться с одним вариантом ран-тайм библиотеки . Эта библиотека должна будет соответствовать стандарту ISO C . Если вы напишите нестандартную библиотеку , все ваши программы будут непортабельны на другие ОС .

Существует большое количество си-шных функций , которые платформенно-независимы . например , большинство <string.h> и <wchar.h> могут быть просто скопированы .

Другие функции наоборот зависят от версии ядра , например <stdio.h> , даже printf() . По поводу printf(): большинство си-шных библиотек используют шаблон printf() для генерации аналогичных fprintf(), sprintf() и т.д. Нужно уметь пользоваться функциями , которые посылают символьный вывод на абстрактный интерфейс типа stream.

RTL несет ответственность не только за переносимость приложений , но и за нормальную работу ядра . Такие вещи , как strcpy() или malloc()) должны быть реализованы максимально просто и эффективно . Они должны быть доступны любому драйверо-писателю .


OS-Specific Support
С точки зрения ядра си ,вообще говоря, неидеален в плане получения доступа к железу . Это приводит к тому , что приходится либо делать инлайн , либо писать целые куски на чистом ассемблере . Поддержка инлайна существует для gcc для всех платформ . Чего нельзя сказать ни о Visual C++ , ни тем более о Borland C++. Gcc-инлайн будет пожалуй что помощнее- например , в нем можно явно указать , какие регистры можно модифицировать внутри инлайна .

Ассемблерный код может потребоваться и в user mode для вызова системных функций . Можно поместить вызовы прерываний прямо в RTL (как в MS-DOS ), или создать отдельную библиотеку (как в Windows NT ntdll.dll).

C++ in the Kernel
Точка зрения в линуксе на использование плюсов известна . В то же время некоторые целиком пишут оси на плюсах . При использовании плюсов прийдется потратить много усилий на промежуточный фрейм-ворк , помня о том , что плюсы имеют ограничения в плане переносимости .

Вам прийдется постоянно помнить о дилемме new - delete. Например , если вам понадобится какой-то глобальный обьект класса , нужно будет очень хорошо разобраться , как это делается у вашего вендора , возможно прийдется изучить изнутри что-то типа crt0.c. Если вы не дай бог захотите использовать в ядре try/catch , возможно вам тогда прийдется изобретать колесо , поскольку это уже реализовано в вашем нативном компиляторе , с помощью которого вы будете собирать свое плюсовое ядро .

Использование плюсовых exception handling и virtual classes вряд ли будет оправдано по причине их тормознутости . Ядро должно работать максимально быстро , а прелести дизайна имеют к этому мало отношения .


Итого
Написание ОС на языке C , прямо скажем , занятие гораздо более продуктивное , нежели на ассемблере . Такой компилятор как gcc - это безусловно выбор номер 1 .
И это правильно .


Оставьте свой комментарий !

Ваше имя:
Комментарий:
Оба поля являются обязательными

 Автор  Комментарий к данной статье
screw
  Про виртуальные ф-ии в ядре написан полный бред.
2007-08-02 15:41:45