Page 1 of 9

Тех. Задание на Микро-Ядро

Posted: Sun Apr 08, 2007 10:15 am
by w-tools
Приветствую всех, уважаемые товарисчи !!! :-) :-) :-)

Позвольте мне представить, так сказать небольшое тех. задание
для создания микроядерной OS.
Надеюсь что этот материал сподвигнет многих программистов к написанию
реального кода, а не реального флейма :-) :-) :-)

Сперва необходимо написать три бинарных файла и один конфигурационный файл.
Это четыре файла:

1.0 Начальный загрузчик 'loader.com'
2.0 Конфигурационный файл 'kernel.cfg'
3.0 Микро Ядро 'kernel.bin'
4.0 Отладочный драйвер 'debug.run'

(Предлагаю для всех исполняемых файлов назначать расширение '.run' от
слова RUN, чтобы никому небыло обидно :-) )


1.0 Начальный загрузчик 'loader.com'

Начальный загрузчик должен уметь перевести процессор в защищенный режим
(плоская модель памяти), загрузить в память компьютера микроядро,
конфигурационный файл, приложения и драйвера которые прописаны в
конфигурационном файле. Затем начальный загрузчик должен передать управление
на микроядро, после чего микроядро берет управление всей системой на себя.

Из-за того что, процесс начальной загрузки на IBM PC достаточно кривой то
придется начальный загрузчик разделить на две части. Первая часть бутовая,
вторая все что не поместилось в 'BOOT RECORD'. Лично мне очень понравился
менеджер загрузок под названием 'SyMon'(правда он share ware) И мне кажеться
что загрузчикам типа Lilo и Grub очень далеко по интуитивности и понятности
до бутового загрузчика SyMon

Для простоты и функциональности, думается сперва имеет смысл сделать простой
'досовый' загрузчик 'loader.com'


2.0 Конфигурационный файл

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

2.1 Пример конфигурационного файла 'kernel.cfg'

Пример конфигурационного файла:

#name="kernel config file" // Обязательный параметр(идетификатор) ставиться в начале конфигурационного файла
#title="Пример конфигурационного файла"; // Не обязательный параметр (заголовок)


/* Параметры для загрузчика */
/* Приложения и драйвера для загрузки в память*/

#load="fdd01/kernel.bin"; // Загрузить c флоппи диска ядро (можно не писать загружается по умолчанию)
#load="fdd01/kernel.cfg"; // Загрузить конфигурационный файл (можно не писать загружается по умолчанию)
#load="fdd01/debug.run"; // Загрузить отладочный драйвер
#load="fdd01/video.run"; // Загрузить драйвер дисплея (сервер)
#load="fdd01/keybord.run"; // Загрузить драйвер клавиатуры (сервер клавиатуры)
#load="fdd01/hdd.run"; // Загрузить драйвер жесткого диска
#load="fdd01/mouse.run"; // Загрузить драйвер мышки (сервер мышки)
#load="fdd01/cd-dvd.run"; // Загрузить драйвер CD-ROM, DVD-ROM
#load="fdd01/far/far.run"; // Загрузить файловый менеджер FAR
#load="fdd01/fasm/fasm.run"; // Загрузить ассеблер Fasm
#load="fdd01/drv/mouse.run"; // Загрузить драйвер мышки
#load="fdd01/tpadv/tpad.run"; // Загрузить текстовый редактор
#load="fdd01/tcpip/tcpip.run"; // Загрузить TCP-IP драйвер(стек)
#load="fdd01/drv/usb.run"; // Загрузить USB драйвер(стек)


/* Параметры для ядра */

#startmsg="ON" // включить вывод информации о процессе загрузки ядра
#debug="ON" // включить накопление в ядре отладочной информации
#debugrun="ON" // включить вызов драйвера 'debug' про любому событию в системе

/* приложения и драйвера для запуска (из памяти) */

#run="fdd01/debug.run"; // Запустить отладочный драйвер
#run="fdd01/video.run"; // Запустить драйвер дисплея (сервер)
#run="fdd01/keybord.run"; // Запустить драйвер клавиатуры (сервер клавиатуры)
#run="fdd01/hdd.run"; // Запустить драйвер жесткого диска
#run="fdd01/mouse.run"; // Запустить драйвер мышки (сервер мышки)
#run="fdd01/cd-dvd.run"; // Запустить драйвер CD-ROM, DVD-ROM
#run="fdd01/far/far.run"; // Запустить файловый менеджер FAR
#run="fdd01/fasm/fasm.run"; // Запустить ассмеблер Fasm
#run="fdd01/drv/mouse.run"; // Запустить драйвер мышки
#run="fdd01/tpadv/tpad.run"; // Запустить текстовый редактор
#run="fdd01/tcpip/tcpip.run"; // Запустить TCP-IP драйвер(стек)
#run="fdd01/drv/usb.run"; // Запустить USB драйвер(стек)


3.0 Микро Ядро 'kernel.bin'

Микроядро должно выполняться в нулевом кольце и должно уметь выполнять
следующие функции:

- менеджер памяти (выделять/освобождать куски памяти произвольного размера)
- менеджер задач (запускать/остонавливать выделенные куски памяти и
переключаться между задачами по прерыванию от таймера)
- регистратор прерываний (регистрировать прерывания от различных устройств
и при наличии соответствующего драйвера передавать на него управление)

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

3.1 Функции микроядра

Функции работы с памятью:


1. Вернуть размер свободного количества памяти

2. Выделить кусок памяти определенного размера с определенными свойствами из
общего обьема памяти компьютера(создать буфер).

Параметры выделенного куска памяти.

- Размер куска памяти (кратный 4-м Kb)

- Порядковый номер куска

- Уникальный номер куска

- Литерное имя куска

- Зависммый кусок памяти, зависимый кусок памяти автоматический
удаляется если удалить родительский процесс(приложение) которое
послало запрос на выделение этого куска памяти

- Не зависимый кусок памяти, не зависимый кусок памяти остается
в памяти после удаления родительского процесса(приложения/драйвера)


- Общий (доступный) для всех приложений на чтение (-r)

- Общий (доступный) для всех приложений на запись (-w)

- Приватный, доступный только для родительского процесса
(приложения/драйвера)

3. Удалить выделенный кусок памяти, (освободить память)

4. Изменить параметры выделенного куска памяти


Функции работы с задачами(приложениями/драйверами)

1. Создать из выделенного куска памяти(буфера) задачу (установить флаг,
что этот кусок памяти является задачей) К атрибутам буфера добавляется
атрибут задачи


2. Превратить задачу обратно в кусок памяти(буфер) - снять атрибут(флаг)
задачи.


3. Установить задачу в очередь на выполнение по прерыванию от таймера.
По другому говоря зарегестрировать приложение в таблице менеджера
задач или запустить пиложение на выполнение. Эта функця запускает
простое приложение

4. Снять задачу из очереди на выполнение по прерыванию от таймера

5. Установить задачу на выполнение по указанному в параметрах функции
прерыванию (аппаратному или программному). Это значит что задача
(драйвер, приложение) единолично установила (захватило) прерывание.
Эта фукция предназначена для создания реал тайм драйверов

6. Освободить захваченное прерывание

7. Пропустить выполнение задачи. Передать управление на следующее в
очереди задач по таймеру приложение или в случае если пришло аппаратное
(программное) прерывание вернуть упраления ядру

8. Принудидельно передать управление на указанное в параметрах функции
приложение.()


Сервисные функции ядра:

1. Вернуть версию ядра

2. Перезагрузить комьютер

3. Удалить задачу (Kill)

4. Горячий рестарт ядра

5. Вернуть тип процессора
и т.п.

3.2 Дополнительные требования к микроядру

Для простоты и скорости выполнения, микроядро ядро должно писаться
исключительно на Ассемблере (скорее всего FASM). Должно иметь обильные
коментарии :-) :-) :-).
При написании ядра должны использоваться 32-х
разрядные команды и регистры хотя это преведет к незначительному
увеличению размеров микроядра. И самое главное в том чтобы микро ядро
запускалось и раьотало на I386
При написании микроядра нужно предусмотреть соответствующие буферы для
вывода вних отладочной информации и возможность включения режима
#debugrun="ON" для передачи управления отладочному драйверу по любому
событию в системе !!!


4.0 Отладочный драйвер 'debug.run'

Отладочный драйвер 'debug.run' будет хорошим примером для создания
любого драйвера. Так как на начальном этапе нет ни одного драйвера,
то отладочный драйвер будет иметь в себе драйвер дисплея (консольный),
драйвер клавиатуры, драйвер флопи диска и мышки)

Отладочный драйвер будет запускаться при любом событии в системе и
выводить соответствующую информацию. Если говорить более точно то
отладочный драйвер должен представлять из себя настоящий многофункцио
нальный консольный дебаггер !!!



Товарисчи программисты !!! Оособенно те кто 'расколол' защищенный режим,
от вас 'код' и 'исходники' !!! :-) :-) :-)

P.S. Продолжение следует...

Posted: Sun Apr 08, 2007 6:29 pm
by Phantom-84
Нормальное объявление: "Организую операционную систему, недорого, в смысле от вас потребуется лишь выполнить небольшое техническое задание - все это реализовать" :) :) :)

Posted: Mon Apr 09, 2007 2:40 am
by Nameless
Ню-ню... А переводить ОС в защищенный режим... А где планируется хранить GDT и LDT? Уж не в загрузчике ли?

Нужно сначала писать загрузчик. Это верно. Причем, за основу можно взять стандартный кусок ядра от колибри.
Только вот под GDT и LDT нужно зарезервировать какой-то участок памяти... Какой? Причем, было бы неплохо сначала выделить из текущего ядра загрузчик и работать над текущим ядром. Я вот сейчас еще занят изучением исходников...

Posted: Mon Apr 09, 2007 2:43 am
by Nameless
Еще я настоятельно настаиваю на обсуждении изменений в ядре за исключением багфиксов на форуме. Я считаю, что это упростит понимание принципов построения ядра и упростит разработку, даст более четкую архитектуру.

Posted: Tue Apr 10, 2007 2:16 am
by N†OSKRNL
А переводить ОС в защищенный режим
а про еденичку в СR1 ничево не слышал?
А где планируется хранить GDT и LDT?
IDT по нулю... 2кило на весь тейбл... GDT - пару селекторов хватит (32-байта от силы, на код да данные).. LDT/TSS ф топку...
Нужно сначала писать загрузчик
да нах? вон - выгрузил DOS, куданить за предел базового метра. состояние запомнил. коли захочиться в рилмод вернуться если что.
участок памяти...
да колбасить мона где угодно - в старой доброй базовой памяти например... вон как сказал бил гатес, "640кб - хватит на всех".

Posted: Tue Apr 10, 2007 8:30 pm
by Nameless
ntoskrnl, я все понимаю... Вообще все. но... Ты не понял... Или я вообще туплю, чтоли... Существующее ядро поделить на два файла (родин ищз них загрузчик). Короче, дальше сначала написал многа, потом все стер... Когда будет результат - тогда выложу.

Posted: Tue Apr 10, 2007 8:50 pm
by N†OSKRNL
да.. не всё так сразу. Ядро Колибри довольно навороченое, тож не сразу строилось. тут нада потихоньку осиливать. просто
прикинул простейшую модель... среду жизнеобитания, так сказать. Важен то ведь не загрузчик (loader), а сам callбасер.

Posted: Tue Apr 10, 2007 9:01 pm
by DmitrySokolowsky
N†OSKRNL, тебе бы всё колбаситься.

Posted: Sat Apr 14, 2007 6:55 pm
by O01eg
а какое отношение имеет эта тема к ядру Колибри?

Posted: Sat Apr 14, 2007 7:26 pm
by Nameless
Прямое. Читайте внимательнее.

Posted: Sun Apr 22, 2007 4:09 am
by hidden
Неинтересна тема, я сам недавно обдумывал некоторые детали работы системы. Думаю нужно детализировать всё настолько, насколько это возможно.

Предлагаю некоторые уточнения, корректировки, оптимизации:

- Сделать не 1, а 2 конфигурационных файла, первый для загрузки ядра и базовых драйверов(диски и системы ввода вывода такие как дисплей и клавиатура), а второй для конфигурации ядра, загрузки остальных драйверов и первой программы интерфейса пользователя у которой будет уже свой конфигурационный файл.

- Упростить синтаксис конфигурационного файла, ос ведь на ассемблере, вот и синтаксис должен быть как в ассемблере, зачем эти лишние символы [#=;/*]:
Файл: fdd01/boot.cfg

Code: Select all

  name "Boot config file" 	; Обязательный параметр(идентификатор) ставиться в
  				; начале конфигурационного файла 

; Параметры для загрузчика 
; Приложения и драйвера для загрузки в память

  init 0x00080000		; С этого места будут загружаться нижеописанные файлы

  load "fdd01/kernel.bin"	; Загрузить ядро
  load "fdd01/kernel.cfg"	; Загрузить конфигурационный файл ядра
  load "fdd01/debug.run"	; Загрузить отладочный драйвер
  load "fdd01/video.run"	; Загрузить драйвер дисплея
  load "fdd01/keybord.run"	; Загрузить драйвер клавиатуры
  load "fdd01/hdd.run"		; Загрузить драйвер жесткого диска
     
  call 0x00080000 		; Эта строка должна быть единственная, сюда будет
  				; передано управление после загрузки всех
  				; вышеописанных файлов
Команды 4х байтовые, для упрощения анализа.

- Загрузчик должен перевести процессор в unreal mode, прочитать конфигурационный файл, а также всё то там написано средствами БИОС, и передать управление по указанному адресу, предварительно поместив адрес массива адресов загруженных файлов c последним элементом равным нулю в eax, в esp значение eax-4, а все остальные регистры обнулить.

- Загрузчик также должен уметь пользоваться файловой системой, для чего нужно вынести функции работы с файловыми системами в отдельные .inc файлы, для последующего расширения возможностей.

- Ядро должно подготовить и загрузить gdt и idt, включить защищённый режим, включить страничную адресацию, выделить для каждого файла своё адресное пространство с базовым адресом указанным в заголовке, выполнить точки входа в каждый загруженный файл, имеющий заголовок исполняемого файла, при этом передовая в eax тот лист, который передал загрузчик, а устанавливать хуки на прерывания и сообщать ядру функции для работы с ними, драйвера будут вызывать программное прерывание выделенное для взаимодействия с драйверами(только с ними), если драйвер вернул код неудачи, ядро должно выгрузить его, на этом этапе загрузки нельзя читать или писать в файлы, всё базовые файлы должны уже быть прочитаны загрузчиком.

- Общедоступные куски памяти: у каждого исполняемого файла должен быть базовый адрес, а также они во время выполнения могут попросить выделить память по произвольному виртуальному адресу, что может конфликтовать с общедоступными кусками. Общедоступным кускам следует назначать уровень доступности(для текущего процесса, для драйверов и для остальных процессов), а также именовать, выдавать приложениям/драйверам только по запросу с указанием имени, адреса в виртуальном адресном пространстве данного процесса/драйвера(куда его проецировать), длины проекции, а также запрашиваемого доступа(-r -rw).

- Независимые куски памяти: Это нехороший и опасный механизм, приложение может быть завершено до того, как освободит эту память или специально создаст и завершиться, что обычно делают вирусы при попадании в нулевое кольцо. Думаю, не стоит использовать этот механизм.

- debugrun – Если не нужна отладка, можно просто закомментировать строку:

Code: Select all

  load "fdd01/debug.run"	; Загрузить отладочный драйвер
- Для стека выделять память доступную только для чтения и записи, для защиты от переполнений.

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

Posted: Mon Apr 23, 2007 6:08 pm
by Nameless
Угу. То есть, вы предлагаете писать с нуля, не аботая над совместимостью...?

Posted: Tue Apr 24, 2007 2:57 am
by hidden
Nameless wrote:Угу. То есть, вы предлагаете писать с нуля, не аботая над совместимостью...?
Насчёт совместимости с драйверами, какая-ж тут может быть совместимость, если там они вроде закомпилированы внутрь ядра, а тут в отдельных файлах, а формат запускаемых файлов ещё вообще не обговаривался, там можно вообще сделать поддержку любого формата.

Re: Тех. Задание на Микро-Ядро

Posted: Wed Apr 25, 2007 3:43 pm
by SHREDER
w-tools wrote: Синтаксис конфигурационного файла для облегчения обработки будет близок к
синтаксису ясыка Си.

2.1 Пример конфигурационного файла 'kernel.cfg'

Пример конфигурационного файла:

#name="kernel config file" // Обязательный параметр(идетификатор) ставиться в начале конфигурационного файла
#title="Пример конфигурационного файла"; // Не обязательный параметр (заголовок)


/* Параметры для загрузчика */
/* Приложения и драйвера для загрузки в память*/

#load="fdd01/kernel.bin"; // Загрузить c флоппи диска ядро (можно не писать загружается по умолчанию)
#load="fdd01/kernel.cfg"; // Загрузить конфигурационный файл (можно не писать загружается по умолчанию)
#load="fdd01/debug.run"; // Загрузить отладочный драйвер
#load="fdd01/video.run"; // Загрузить драйвер дисплея (сервер)
#load="fdd01/keybord.run"; // Загрузить драйвер клавиатуры (сервер клавиатуры)
#load="fdd01/hdd.run"; // Загрузить драйвер жесткого диска
#load="fdd01/mouse.run"; // Загрузить драйвер мышки (сервер мышки)
#load="fdd01/cd-dvd.run"; // Загрузить драйвер CD-ROM, DVD-ROM
#load="fdd01/far/far.run"; // Загрузить файловый менеджер FAR
#load="fdd01/fasm/fasm.run"; // Загрузить ассеблер Fasm
#load="fdd01/drv/mouse.run"; // Загрузить драйвер мышки
#load="fdd01/tpadv/tpad.run"; // Загрузить текстовый редактор
#load="fdd01/tcpip/tcpip.run"; // Загрузить TCP-IP драйвер(стек)
#load="fdd01/drv/usb.run"; // Загрузить USB драйвер(стек)


/* Параметры для ядра */

#startmsg="ON" // включить вывод информации о процессе загрузки ядра
#debug="ON" // включить накопление в ядре отладочной информации
#debugrun="ON" // включить вызов драйвера 'debug' про любому событию в системе

/* приложения и драйвера для запуска (из памяти) */

#run="fdd01/debug.run"; // Запустить отладочный драйвер
#run="fdd01/video.run"; // Запустить драйвер дисплея (сервер)
#run="fdd01/keybord.run"; // Запустить драйвер клавиатуры (сервер клавиатуры)
#run="fdd01/hdd.run"; // Запустить драйвер жесткого диска
#run="fdd01/mouse.run"; // Запустить драйвер мышки (сервер мышки)
#run="fdd01/cd-dvd.run"; // Запустить драйвер CD-ROM, DVD-ROM
#run="fdd01/far/far.run"; // Запустить файловый менеджер FAR
#run="fdd01/fasm/fasm.run"; // Запустить ассмеблер Fasm
#run="fdd01/drv/mouse.run"; // Запустить драйвер мышки
#run="fdd01/tpadv/tpad.run"; // Запустить текстовый редактор
#run="fdd01/tcpip/tcpip.run"; // Запустить TCP-IP драйвер(стек)
#run="fdd01/drv/usb.run"; // Запустить USB драйвер(стек)
Помоему тут лучше заюзать XML лину вроде. Благо для его расшифрования давно есть DOM и проч.

<?xml version="1.0" encoding="UTF-8"?>
<config name="kernel config file">

<loader>
<load>
<kernel location="fdd01/kernel.bin"/>
<drivers dir="fdd01/sys/drivers/" configdir="fdd01/sys/config">
<driver name="debug" location="debug.drv"/>
<driver name="dispay"
location="display.drv"
config="video.conf" />
<driver name="hdr_main"
location="hdrmain.drv"
config="hdr.conf"/>
<driver name="hdr_ext"
location="hdrext.drv"
config="hdr.conf"/>
...................................................................
</drivers>
</load>

<kernel_config>

<memory_dispatcher config="fdd01/sys/config">
<vmem config="virtualmemory.conf">
<swapping>
<startsector value="0x01000000"/>
<endsector value="0x05000000"/>
</swapping>
.............................................
</memory_dispethcer>

<task_dispatcher config="fdd01/sys/config/task_dispetcher"/>

<demons>
<demon name="time_server"
location="fdd01/sys/service/time.exe"
config="config="fdd01/sys/config/time_server.conf">
<demon name="net_service">
<location>fdd01/sys/service/nettask.exe</location>
<protocol drv="fdd01/sys/service/tcpip.drv"
status="active"/>
<protocol drv="fdd01/sys/service/ipxspx.drv"
status="passive"/>
</demon>
................................................
</demons>


<shell config="fdd01/sys/config">
<location>fdd01/sys/shell/winengine.exe</location>
<location>fdd01/sys/shell/comand.exe</location>
<textmode status="off" width="80" heiht="25"/>
<graphmode status="onn" config="video.conf">
</shell>
</kernel_config>

</loader>

Загрузка в память - автоматичекси означает запуск. Каждый драйвер или демон может иметь собственный конфигурационый файл, параметры он получает не из него, а ему их передает диспетчер устройств (диспетчер задачь для демонов) через некий интерфейс портов настройки. Наргромождение таких XML образует системный реестр. Но в отличие от реестра винды это текстовые файлы которые можно пробакапить или поправить в ручную и смерть реестра не означает смерть системы.

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

Короче все сие можно в общем прикрутить к колибри. Только заниматся этим по всей видимости никто не будет, ибо исходники колибри на 60-70% это исходники минуэта, в которых черт ногу сломит. Так что ежели переписывать все на С++ тогда пожалуй сие очень даже подойдет.

з.ы. Я суда в ксмл прикрутил настройку тестового режима, спопинга виртуальной памяти в общем все чего нет но нужно. Короче все сие мое личное ИМХО не нравится дело ваше можете меня материть.

Posted: Wed Apr 25, 2007 7:08 pm
by bw
Матерю :-).

Во первых. Если ты решил использовать XML (а не схожий язык разметки), то используй DTD, а лучше пространства имен, а значит и обработчик, который будет жевать этот XML должен иметь валидатор (для XSD) и уметь работать с известными схемами и с неизвестными. Я по опыту скажу - лучше удавиться. Получится может не очень большой код, но очень сложный.

Во вторых, если начнется переход на Си(++), я начну переходить на L4 ядра, Minix3 или другие. Под этими ядрами сделано значительно больше и переписывать их не вижу смысла. Я по природе не мазахист. Тот же XviD проигрыватель я делаю не переписыванием Си кода XviD на Pascal, а линковкой уже скомпилированного. Потому что какой смысл. Если тебе очень нравится Си (я не имею возражений). Возми тот же минимальный L4Ka::Pistachio и дополняй его серверами что бы получить обратную совместимость с текущей версией KolibriOS. Я думаю все скажут тебе спасибо.

..bw