【自制操做系统08】中断

因为中断这块的知识和代码都占较大篇幅,所以分红两章来说,本章不包含任何中断的代码,只讲理论部分,以及中断的大概流程。代码实现部分由下一章来说解html

【自制操做系统09】中断的代码实现linux

1、到目前为止的程序流程图

为了让你们清楚目前的程序进度,画了到目前为止的程序流程图,以下。git

2、什么是中断

这里咱们先从形象的角度来描述,中断就是让操做系统中止手中正在进行的工做,先把中断信号对应的处理程序执行完毕,再回到以前的程序中继续进行,这样一个机制。编程

一个很形象的说法是,咱们的操做系统就是 中断驱动 的,能够把操做系统简单理解为一个 死循环,无时无刻不在等待中断的来临,被动 地执行相应的任务。数组

while(true){
    操做系统代码
}

3、中断的分类

外部中断

外部中断经过两个引脚链接到 CPU 上,一个是可屏蔽中断 INTR,一个是不可屏蔽中断 NMIide

  • INTR:硬盘、打印机、网卡等设备发出的中断信号,可经过 eflags 寄存器的 IF 位将全部这些外部设备的中断屏蔽
  • NMI:电源掉电、内存读写错误、总线奇偶校验错误等灾难性的错误,不可屏蔽,CPU 必须马上处理

对于可屏蔽中断,Linux 的处理方式是分红 上半部下半部。上半部执行时关闭中断,马上执行完毕;下半部执行时打开中断,此时若是有其余中断进来,则让给其余中断(也是上半部执行完毕)。学习

内部中断

内部中断可分为 软中断 和 异常,两者均是不可屏蔽的(即不受 eflags 的 IF 位影响)测试

  • 软中断:就是软件发起的中断,最多见的也是咱们以后进行系统调用的,就是 int 8位当即数,可表示 256 中中断。还有一些不经常使用的,甚至能够叫作异常,下面简单列出
    • int3:中断向量号3,调试断点指令
    • into:中断向量号4,中断溢出指令
    • bound:中断向量号5,检查数组索引越界指令
    • ud2:中断向量号6,未定义指令,经常使用于软件测试中主动发起这个中断
  • 异常:指令执行期间 CPU 内部产生的错误引发,如分母为 0 将发起 6 号中断(异常),未定义的指令发起 6 号中断
    • Fault(故障):可恢复的错误。发生此中断时,CPU 将机器状态恢复到异常以前的状态,以后调用中断处理程序,结束后返回。常见的如 缺页异常
    • Trap(陷阱):有意的异常。一般是调试程序中用 int3 指令主动触发。
    • Abort(终止):不可恢复的异常。直接将此程序从进程表中去掉。

4、中断号

咱们知道一个中断对应着一个 中断号(中断向量号),下面列表说明操作系统

中断号 含义 来源 类型 是否有错误码
0 divide error DIV and IDIV instructions Fault
1 debug any code or data reference Fault/Trap
2 NMI Interrupt NMI Interrupt
3 Breakpoint INT3 instruction Trap
4 Overflow INTO instruction Trap
5 bound range exceeded BOUND instruction Fault
6 invalid opcode UD2 instruction or reserved opcode.1 Fault
7 device not available floationg-point or WAIT/FWAIT instruction Fault
8 double fault any instruction that can generate an exception, an NMI, or an INTR Fault Y(0)
9 CoProcessor Segment Overrun Floating-point instruction.2 Fault
10 invalid TSS task switch or TSS access Fault Y
11 segment not present loading segment registers or accessing system segments Fault Y
12 stack segment fault stack operations and SS register loads Fault Y
13 general protection any memory reference and other protection checks Fault Y
14 page fault any memory reference Fault Y
15 reserved
16 floating-point error floating-point or WAIT/FWAIT instruction Fault
17 alignment check any data refrence in memory.3 Fault Y(0)
18 machine check error codes and source are model dependent.4 Fault
19 SIMD floating-point exception SIMD floating-point instruction5 Fault
20-31 reserved
32-255 maskable interrupts External Interrupt from INTR pin or INT n instruction Interrupt

5、中断描述符表 IDT

咱们先来回顾一下上一讲 【自制操做系统07】深刻浅出特权级 说的四种门描述符

type值 存在位置 用法
任务门 0101 GDT、LDT、IDT 与TSS配合实现任务切换,不过大多数操做系统都不这么玩
中断门 1110 IDT 进入中断后屏蔽中断(eflags的IF位置0),linux利用此实现系统调用,int 0x80
陷阱门 1111 IDT 进入中断后不屏蔽中断
调用门 1100 GDT、LDT 用户用call或jmp指令从用户进程进入0特权级

你看,正如上一讲所说,中断门进入后先是屏蔽了中断,也就是中断例程的 上半部,程序中能够随时打开中断,也就天然到了 下半部,这就是 linux 系统的处理方式。debug

如何找到中断描述符表呢?你猜的没错,正如找 段描述符表页表 等同样,有个 IDTR 寄存器存储它的位置(0-15位是表界限,16-47位表示表基址),有个 lidt 指令负责加载 IDTR。经典作法,咱们见过太屡次了,就很少说啦,不理解的能够从本系列开头开始看哟。

6、中断处理过程

上图就表示了整个中断处理的过程,不过还有几处图中没有显示

特权级检查:CPL <= 门描述符DPL && CPL > 目标代码段DPL

栈的处理:将 CS、EIP、EFLAGS、SS、ESP 寄存器的值压入中断处理程序使用的栈

7、8259A芯片

咱们以前说过,外部设备发出中断信号,进入 CPU 的 INT 引脚上。但若是有多个外部设备近乎同时发送中断信号,CPU 先处理哪个呢?未被处理的中断信号又记录在哪里呢?这时候就须要有个 中间的代理设备 来负责这个事情。

这个代理设备叫作 可编程中断控制器 PIC,其中 8259A 芯片是最多见的一种,咱们这里把它的内部结构展现出来,因为是硬件相关,就不展开细说了,但因为以后要为其进行编程,因此你们先有个印象。

8、中断代码实现

因为到此篇幅过长,且中断代码的实现也是须要很大篇幅描述的,包括 可编程中断控制器的初始化,IDT 的初始化,以及中断例程代码的编写,因此将放在下一章进行讲解。

【自制操做系统09】中断的代码实现

写在最后:开源项目和课程规划

若是你对自制一个操做系统感兴趣,不妨跟随这个系列课程看下去,甚至加入咱们,一块儿来开发。

参考书籍

《操做系统真相还原》这本书真的赞!强烈推荐

项目开源

项目开源地址:https://gitee.com/sunym1993/flashos

当你看到该文章时,代码可能已经比文章中的又多写了一些部分了。你能够经过提交记录历史来查看历史的代码,我会慢慢梳理提交历史以及项目说明文档,争取给每一课都准备一个可执行的代码。固然文章中的代码也是全的,采用复制粘贴的方式也是彻底能够的。

若是你有兴趣加入这个自制操做系统的大军,也能够在留言区留下您的联系方式,或者在 gitee 私信我您的联系方式。

课程规划

本课程打算出系列课程,我写到哪以为能够写成一篇文章了就写出来分享给你们,最终会完成一个功能全面的操做系统,我以为这是最好的学习操做系统的方式了。因此中间遇到的各类坎也会写进去,若是你能持续跟进,跟着我一块写,必然会有很好的收货。即便没有,交个朋友也是好的哈哈。

目前的系列包括

相关文章
相关标签/搜索