Разработка монолитной Unix подобной OS — Библиотека С (2)

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!

В предыдущей статье мы научились запускать Hello World ядро и написали пару функций для работы со строками. Теперь пришло время расширить библиотеку С чтобы можно было реализовать kprintf и другие необходимые функции. Поехали!

Оглавление


  1. Система сборки (make, gcc, gas). Первоначальная загрузка (multiboot). Запуск (qemu). Библиотека C (strcpy, memcpy, strext).
  2. Библиотека C (sprintf, strcpy, strcmp, strtok, va_list ...). Сборка библиотеки в режиме ядра и в режиме пользовательского приложения.
  3. Системный журнал ядра. Видеопамять. Вывод на терминал (kprintf, kpanic, kassert).
  4. Динамическая память, куча (kmalloc, kfree).
  5. Организация памяти и обработка прерываний (GDT, IDT, PIC, syscall). Исключения.
  6. Виртуальная память (каталог страниц и таблица страниц).
  7. Процесс. Планировщик. Многозадачность. Системные вызовы (kill, exit, ps).
  8. Файловая система ядра (initrd), elf и его внутренности. Системные вызовы (exec).
  9. Драйверы символьных устройств. Системные вызовы (ioctl, fopen, fread, fwrite). Библиотека C (fopen, fclose, fprintf, fscanf).
  10. Оболочка как полноценная программа для ядра.
  11. Пользовательский режим защиты (ring3). Сегмент состояния задачи (tss).

Библиотека С


Сначала необходимо реализовать типы с явным указанием размерности.

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

typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned int u_int;
typedef unsigned int u_long;

Не помешает и ввести Булевский тип.

#pragma once

/* types */
typedef int bool;

#define true 1
#define false 0
#define null 0

Также не помешает нам и парочка макросов для работы с байтами.

typedef unsigned long size_t;

#define HIGH_WORD(addr) ((addr & 0xffff0000) >> 16)
#define LOW_WORD(addr) ((addr & 0xffff))
#define LOW_BYTE(addr) ((addr & 0x00ff))
#define HIGH_BYTE(addr) ((addr & 0xff00) >> 8)

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

typedef size_t* va_list;

#define va_start(l, a) (l = (void*)((size_t)&a) + sizeof(a))
#define va_end(l) (l = (void*)0)
#define va_arg(l, s) (*(s*)(l++))

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

Далее, в видеоуроке мы рассмотрим реализацию следующих библиотечных функций. Реализация не претендует на оптимальность и полноту, но на простоту и читаемость думаю претендует. Отмечу только что мы используем потокобезопасную реализацию функции strtok, которая называется strtok_r. А функции strinv и strext мы придумали сами в прошлом уроке. Если ты знаком с языком С, думаю тебе будут знакомы почти все перечисленные ниже функции.

extern int strlen(const char* s);
extern char* strcpy(char* s1, const char* s2);
extern char* strncpy(char* s1, const char* s2, u_int n);
extern void* memcpy(void* buf1, const void* buf2, u_int bytes);
extern void* memset(void* buf1, u8 value, u_int bytes);
extern int strcmp(const char* s1, const char* s2);
extern int strncmp(const char* s1, const char* s2, u_int n);
extern char* strcat(char* s1, const char* s2);
extern char* strext(char* buf, const char* str, char sym);
extern int strspn(char* str, const char* accept);
extern int strcspn(char* str, const char* rejected);
char* strchr(const char* str, char ch);
extern char* strtok_r(char* str, const char* delims, char** save_ptr);
extern char* memext(void* buff_dst, u_int n, const void* buff_src, char sym);
extern char* itoa(unsigned int value, char* str, unsigned int base);
extern unsigned int atou(char* str);
extern char* strinv(char* str);
extern unsigned int sprintf(char* s1, const char* s2, ...);
extern unsigned int snprintf(char* s1, u_int n, const char* s2, ...);
extern unsigned int vsprintf(char* s1, const char* s2, va_list list);
extern unsigned int vsnprintf(char* s1, unsigned int n, const char* s2, va_list list);

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

Ссылки


Разработка монолитной Unix подобной OS — Начало
Видеоурок к этой статье
Исходный код (тебе нужна ветка lesson2)

Список литературы


  1. James Molloy. Roll your own toy UNIX-clone OS.
  2. Зубков. Ассемблер для DOS, Windows, Unix
  3. Калашников. Ассемблер — это просто!
  4. Таненбаум. Операционные системы. Реализация и разработка.
  5. Роберт Лав. Ядро Linux. Описание процесса разработки.
Источник: https://habr.com/ru/post/466709/


Интересные статьи

Интересные статьи

Материал, перевод которого мы сегодня публикуем, посвящён процессу разработки системы визуализации динамических древовидных диаграмм. Для рисования кубических кривых Безье здесь используется техн...
Почему это вообще появилось здесь? Недавно я написал статью о разработке бота на php с использование laravel+botman для telegram. Самое первое, что написали, цитирую, “стрельба из пушки по вор...
Классическое PHP-приложение — однопоточность, тяжелая загрузка (если вы конечно не пишите на микрофреймворках) и неизбежная смерть процесса после каждого запроса… Такое приложение тяжелое и медле...
В прошлой статье я сказал, что нам пора переходить к потоковым протоколам. Но начав подготовку рассказа о них, я понял, что сам плаваю в одной очень важной теме. Как уже отмечалось, у меня с Лину...
Что, если у вас идея для классного, полезного белка, и вы хотите получить его в реальности? Например, хотите создать вакцину против H. pylori (как словенская команда на iGEM 2008), создав гибридн...