疑难解答
对于操作系统开发过程中发生的各种错误进行疑难解答
虚拟机 / 实体机突然重启
发生了 TripleFault
异常, 需要检查你的操作系统源码
- 是否配置了
IDT
中断描述符表 - 中断向量号对应的
IDT
表项是否为空 - 是否正确处理了
DoubleFault
异常
DoubleFault 异常
发生了一次中断异常时候并没有及时处理导致中断内又发生了一次异常.
- 需检查上一次中断异常的向量号, 错误码等各项信息.
- 处理其他异常的代码是否有漏洞
- 执行环境已经被彻底破坏, 一般的异常处理程序无法解决
特别注意
双重异常时我们默认当前的执行环境已经被彻底破坏, 所以处理时候与其他的中断异常不相同
你需要事先准备好一块完全可用的 1kb 区域用作双重异常的专属栈区, 发生双重异常时需要将rsp切换到该区域
需要准备双重异常专用的页表, 发生时切换到该页表
双重异常内仅作一些简单的信息输出, 不要尝试恢复 (因为你已经无法恢复异常了)
PageFault (最常见)
页异常, 这里需要你根据 cr2
寄存器存储的异常地址来判断
NotPresent
- 如果地址为
0
, 代表发生了空指针异常, 检查你的源码中是否缺少空指针检查. - 地址过小 (如小于
100
字节等) 也可能发生了空指针异常. - 需要检查
cr2
的地址是否被映射.
警告
如果发现 cr2 地址过于离谱, 需要检查程序是否 "跑飞了"
UserMode
- 用户态程序写入或读取了内核区域的内存
GeneralProtectionFault
通用保护性异常, 一般是产生了非法操作导致的CPU异常
- 写入了一些不可用内存 (如未初始化设备直接写入设备MMIO)
- 调度器切换上下文不正确导致寄存器混乱
- 控制寄存器的标志位设置不正确
InvalidOpcode
非法操作码异常, 一般是CPU遇到了未知指令导致的
- CPU可能将数据当作指令执行了
- 确保指令没有问题的情况下检查是否动用了 x86 扩展指令集, 但是CPU不支持扩展指令集
- 如检查出CPU支持扩展指令集但仍然发生此错误, 需要检查该扩展指令集需不需要额外进行启用操作
syscall
指令需要设置MSR
使能才可以使用, 不然也会发生该错误
部分实体机跑不起来我的OS
电脑与电脑之间硬件的实现亦有差距, 无法保证所有硬件厂商都会乖乖按照标准制作.
- 换一种稳妥的方法实现一些有争议的区域
注意
永远不要写死一些地址, 不同实体机甚至是虚拟机之间的内存布局都大相径庭. 可以通过如 ACPI
cpuid
等获取的地址不要写死, 你无法假定这块地址在所有的环境中是永远不会被占用的