|
Kintsugi OS 0.5.0
x86 Monolithic OS
|
Программы выполняются последовательно, одна foreground-программа за раз. GDT содержит ring-3 code/data и TSS; TSS задаёт отдельный 16-КиБ kernel stack. Переход через iret, возврат в ядро через interrupt gate int 0x80 (DPL=3). IOPL=0, I/O bitmap отсутствует: пользовательские инструкции ввода/вывода запрещены.
Каждый запуск получает отдельный CR3. Отображения ядра supervisor-only; пользовательский диапазон 0x40000000..0x80000000. Стек 32 КиБ в конце диапазона, с отсутствующей страницей перед ним. ELF-сегменты проверяются на границы, переполнение, соответствие файлу и alignment, пересекающиеся страницы отклоняются. Writable+executable сегменты отклоняются. Без PAE/NX аппаратного запрета исполнения data/stack нет. ELF ET_EXEC/i386/static; dynamic linker не поддерживается. Лимиты: ELF-файл 1 МиБ, суммарные сегменты 8 МиБ, до 32 аргументов по 1023 байта.
При выходе или пользовательском исключении ядро восстанавливает свой CR3, освобождает пользовательские страницы и таблицы. Ошибка ядра по-прежнему panic. Код завершения виден через status; исключение даёт 128 + vector. Планировщика и принудительной остановки пока нет: бесконечный цикл программы не возвращает shell (IRQ продолжают работать). Это следующий этап, не многозадачная ОС.
На входе _start: [esp]=argc, [esp+4]=argv; argv завершается NULL. Системный вызов: eax=номер, ebx/ecx/edx/esi=аргументы, eax=результат. Остальные регистры сохраняются. Указатели проверяются постранично по user/write битам; пути копируются в буфер ядра, длина до 255 байт.
| Номер | Операция | Аргументы |
|---|---|---|
| 0 | exit | status |
| 1 | console write | buffer, length (до 4096) |
| 2 | file read | path, offset, buffer, capacity (до 4096) |
| 3 | readdir | path, cursor pointer, vfs_dirent pointer |
| 4 | getcwd | buffer, capacity |
| 5 | heap grow | bytes, возвращает начало новой области или 0 |
| 6 | stdin read | buffer, capacity (1..4096), возвращает число байт |
Файловые вызовы используют текущий VFS; readdir-структура пока соответствует vfs_dirent_t i386 ABI. Это собственный ABI, не Linux/POSIX. Нет пользовательских записи файлов и запуска дочерних процессов через syscalls.
Минимальный runtime src/user/runtime.h предоставляет malloc/free и read_stdin. Куча пользователя — до 16 МиБ с адреса 0x60000000; malloc выравнивает на 16 байт, переиспользует и объединяет свободные блоки. Free не возвращает страницы ядру; все страницы освобождаются при выходе. При нехватке RAM частично добавленные страницы также освобождаются при выходе. stdin блокируется с hlt и включёнными IRQ, поддерживает Enter, Backspace, Ctrl+D (EOF) и Ctrl+C (завершение программы с кодом 130). Возвращаемые байты не завершаются NUL; newline включается в результат. При заполнении буфера возвращается его содержимое, остаток строки читается следующим вызовом. /BIN/INPUT.ELF демонстрирует stdin и malloc. Явные относительные пути поддерживаются: ./BIN/ECHO.ELF hello из корня.
make users собирает программы из src/user/. make system-install создаёт каталоги и обновляет перечисленные системные файлы в существующем FAT-образе без форматирования. make run выполняет установку автоматически. Системные файлы перезаписываются; прочие пользовательские файлы не удаляются. Не запускайте установку, пока QEMU использует этот образ.
Копия /BOOT/KERNEL.BIN информационная: BIOS-загрузчик всё ещё читает ядро с загрузочного floppy/ISO, а не из FAT. Настоящий FAT bootloader — отдельная задача.
Shell ищет неизвестные команды в /BIN/<name>.ELF, явный путь запускается напрямую. echo/cat/ls/pwd предпочитают ELF, но сохраняют встроенный fallback для rescue. fault confirm остаётся встроенным тестом panic; пользовательский fault запускается явно как /bin/fault.elf. cd остаётся встроенным, так как меняет состояние shell.
QEMU smoke-test устанавливает программы только на одноразовый диск, проверяет syscall pointers, изоляцию page fault, код завершения и дальнейшую работу shell.