理论讲解:内核初始化

1. 内核模块化

一个好的内核需要清晰的模块划分:

kernel/
├── kernel.c           主入口,初始化流程
├── types.h            基础类型定义
├── string.h / .c      字符串工具函数
├── screen.h / .c      屏幕输出(下一章)
├── port.h             端口I/O操作
└── Makefile

2. 基础类型

freestanding环境中只有少数标准头可用。我们定义自己的类型系统:

#ifndef TYPES_H
#define TYPES_H
 
typedef unsigned char      uint8_t;
typedef unsigned short     uint16_t;
typedef unsigned int       uint32_t;
typedef unsigned long long uint64_t;
 
typedef signed char        int8_t;
typedef signed short       int16_t;
typedef signed int         int32_t;
typedef signed long long   int64_t;
 
typedef uint32_t size_t;
 
#define NULL ((void*)0)
#define true  1
#define false 0
typedef int bool;
 
#endif

3. 端口I/O

OS需要通过I/O端口与硬件通信:

static inline uint8_t inb(uint16_t port) {
    uint8_t result;
    __asm__ volatile("inb %1, %0" : "=a"(result) : "Nd"(port));
    return result;
}
 
static inline void outb(uint16_t port, uint8_t data) {
    __asm__ volatile("outb %0, %1" : : "a"(data), "Nd"(port));
}

这两个函数是与键盘、PIC、PIT等硬件通信的基础。

4. 字符串工具

没有标准库,我们需要自己实现常用函数:

  • memset — 填充内存
  • memcpy — 复制内存
  • strlen — 计算字符串长度
  • strcmp — 比较字符串

5. 初始化流程

kernel_main()
  ├─ 初始化类型系统(编译时,无需运行时动作)
  ├─ 初始化字符串工具(编译时)
  ├─ screen_init()     → 下一章实现
  ├─ idt_init()        → 第9章
  ├─ keyboard_init()   → 第10章
  └─ 进入主循环