Host-Based HAL: еще один путь разработки ОС
HAL в переводе на великий и могучий означает "cлой абстракции от
аппаратуры". То есть предназначен он для того, чтобы свежеразработанную ОС
можно было без особых проблем портировать на другие архитектуры при этом
лишь замененив HAL и перекомпилировав исходные коды. К примеру в HAL можно
(нужно!) разместить низкоуровневый менеджер памяти, с помощью которого
осуществляется постраничное выделение физической памяти и организация
виртуального адресного пространства. В таком случае ядру разрабатываемой
ОС совершенно не нужно будет знать об аспектах организации страничной
адресации на конкретной архитектуре (будь то x86, M68000 или MIPS32), все
что будет ему известно - это абстрактные функции вроде
alloc_page()
, free_page()
и подобные. Эта
абстрактность позволит нам без изменений использовать ядро ОС на
любых архитектурах.
Возникает идея: если само ядро не привязано к конкретной архитектуре, а
взаимодействует с аппаратурой через набор функций HAL, то можно создать
так называемый host-based HAL, который будет выполняться в виде приложения
в какой-либо операционной системе. По сути своей, виртуальные машины вроде
Bochs или VMWare Workstation представляют собой
именно host-based HAL, правда сильно усложненный (они выполняют не
какие-то функции ОС, а весь набор операций процессора).
Сейчас мы в качестве примера рассмотрим мини-ОС и два HAL'а к ней -
один host-based, а второй - аппаратный для архитектуры x86. Вы увидите,
как с легкостью одни и те же исходные коды можно скомпилировать и как для
выполнения в некой виртуальной машине, и как для выполнения на "голом"
процессоре.
Для начала определимся, какие функции будет выполнять наша мини-ОС.
Поскольку усложнить структуру ОС мы успеем всегда, для начала дадим ей две
простых и в большинстве случаев необходимых функции:
1. Вывод на
экран
2. Обработка прерываний
Исходя из функций ОС, интерфейс
ядра ОС с HAL будет осуществляться через следующие
функции:
kputchar(char c)
- вывод символа на
экран
kclear()
- очистка
экрана
register_handler(int vector, void *func)
-
регистрация функции func()
в качестве обработчика прерывания
под номером vector
register_irq_keyboard(void
*func)
- регистрация функции func(char c)
в качестве
обработчика прерывания клавиатуры (эта функция принимает параметр -
нажатый символ)
raise_interrupt(int vector)
-
программный вызов прерывания под номером
vector
enable_interrupts()
- разрешение
обработки прерываний
disable_interrupts()
- запрещение
обработки прерываний
Перечисленные выше функции находятся в HAL и,
следовательно, именно их реализация меняется в каждом конкретном случае и
для каждой конкретной архитектуры.
Само мини-ядро может выглядеть вот таким образом:
void receive_keypress(char c);
void irq_timer(void);
//HAL вызывает эту функцию после инициализации аппаратной части
void system_main()
{
kclear();
kputs("Hello from HAL based OS Demo\n");
register_handler(0x20, irq_timer);
register_irq_keyboard(receive_keypress);
enable_interrupts();
}
//Вывод строки
void kputs(char *string)
{
while(*string){
kputchar(*string);
string++;
}
}
void receive_keypress(char c)
{
kputs("You have pressed: ");
kputchar(c);
kputchar('\n');
}
void irq_timer()
{
}
Исходники host-based HAL'а для этой ОС находятся здесь: host_based_hal.tar.gz.
В качестве хостовой ОС для него используется Linux, ибо, по выражению
одного человека, остальное все от лукавого :). Полученные объектные файлы
HAL'а необходимо слинковать с получившимся из вышеприведенного листинга
объектным файлом ядра kernel.o и после требуемой инициализации HAL
передаст управление ядру системы (а конкретно функции
system_main()
)