理论讲解:内核初始化
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;
#endif3. 端口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章
└─ 进入主循环