图解CPU的实模式与保护模式

哈喽,大家好,我是呼噜噜,好久没有更新old linux了,在上一篇文章Linux0.12内核源码解读(7)-陷阱门初始化中,我们简要地提及了中断,但是中断机制在计算机世界里非常重要,处处都离不开中断,本文来详细聊聊计算机里的中断机制

现代计算机具有多任务处理的能力,可以同时运行着几十上百的任务,如今很难想象,当我们点击鼠标,需要等待计算机中的其他程序全部执行完毕

1956年,IBM 7049机器上首先使用了中断技术,提升了计算机具备应对处理突发事件的能力,并开始使用“中断”这一术语

中断,英文为Interrupt,即打断。当CPU在正常运行程序执行任务时,接收到硬件传过来的中断信号(interrupt request,IRQ),CPU会中断执行当前的工作任务(被打断),转而去处理其他任务,等处理完后再回来继续执行刚才被暂时中断的任务

常见的中断类型

外部中断和内部中断

广义上中断按照中断来源,可分为外部中断和内部中断

  • 外部中断

与CPU执行指令无关,中断信号来自CPU外部,一般指指由计算机外设发出的中断请求,如:键盘中断、打印机中断、定时器中断等。外部中断既有可屏蔽的中断也有不可屏蔽的中断,也是狭义上的中断(interrupt)

它不是由任何一条专门的指令造成的。比如硬盘,打印机,网络适配器,磁盘控制器等外部设备等硬件设备,通过向CPU上的引脚(NMIINTR)发信号,并将异常号放在系统总线上,来触发中断。

中断是异步发生的(不同于同步:执行一条指令的结果),中断处理程序总是返回到当前指令的下一条指令

  • 内部中断

与CPU执行指令有关,中断信号来自CPU内部,一般指通过软件调用的中断,以及由执行指令过程中发生的错误所引起的中断,所以也称为异常(exception),如:trap指令、地址越界、算术溢出、虚存系统的缺页;

我们下文会具体讲讲x86下的异常,接下来还是会继续讲讲中断的其他分类

不可屏蔽中断和可屏蔽中断

中断按照是否可被屏蔽,可分为2类:不可屏蔽中断和可屏蔽中断

  • 不可屏蔽中断

不可屏蔽中断就是当不可屏蔽中断源一旦提出请求,表明问题非常严重或者系统发生了致命的错误,CPU必须立即无条件响应

另外不可屏蔽中断从源头还可以分为,既可由CPU内部产生,也可由外部NMI引脚产生,比如因运算出错(协处理器运算出错、除数为零、运算溢出、单步中断等)或 因硬件出错(如电源掉电,硬件线路故障等)所引起的中断

那什么是NMI引脚?

其实NMI和下面的INTR都是CPU上的引脚,INTR(Interrupt Require)表示可屏蔽中断请求NMI(Nonmaskable Interrupt)表示不可屏蔽中断请求,我们来看下8086CPU的引脚图:

NMI和INTR在上图左下角

所以不可屏蔽中断除了可由 CPU 内部产生,还可以由外部硬件的中断通过NMI这根信号线来通知CPU产生

  • 可屏蔽中断

可屏蔽中断就是当可屏蔽中断源提出请求**,CPU可以响应,也可以不响应;一般是由外部硬件的中断通过INTR这根信号线来通知CPU产生的,比如硬盘,打印机,网卡等外部设备产生中断,这类中断并不会影响计算机的正常运行。不像不可屏蔽中断,它是没有内部中断的,因为内部中断是不可屏蔽的中断**

对于可屏蔽中断,除了受本身的屏蔽位的控制外,还都要受一个总的控制,即CPU标志寄存器中的中断允许标志位IF(Interrupt Flag)的控制,若IF位为1,可以得到CPU的响应,否则得不到响应。而不可屏蔽中断是不受中断标志位IF的影响,不管IF是什么,CPU都必须响应

随着保护模式的流行,Intel意识到使用中断来控制固件已不再是一种解决方案,引入系统管理模式SMM添加到CPU中,与正常中断相反,SMM是CPU的一种特殊模式;要想要输入SMM,必须生成一个系统管理中断SMI,其是在80386的更高版本中引入的,可以用于透明地转换硬件接口

随着奔腾系列的问世,英特尔推出了LAPIC(本地高级可编程中断控制器),INTR和NMI消失了,取而代之的是LINT0LINT1(本地中断),大家了解一下即可,本文的中断还是基于INTR和NMI

硬件中断和软件中断

根据中断源的不同,可以把中断分为硬件中断软件中断两大类

硬件中断是由硬件设备触发的中断,如时钟中断、串口接收中断、外部中断等。当硬件设备有数据或事件需要处理时,会向CPU发送一个中断请求,CPU在收到中断请求后,会立即暂停当前正在执行的任务,进入中断处理程序中处理中断请求。硬件中断具有实时性强、可靠性高、处理速度快等特点

软件中断不是由硬件设备触发的,而是由软件程序主动发起的,如系统调用、软中断、异常、键盘管理中断、显示器管理中断、打印机管理中断等;软件中断需要在程序中进行调用,其响应速度和实时性相对较差,但是具有灵活性和可控性高的特点

与之对应的还有软中断和硬中断

  1. 硬中断是由外部事件引起的因此具有随机性和突发性;硬中断是否可以嵌套的,是否有优先级,由硬件设计体系决定的
  2. 软中断是执行中断指令产生的,无面外部施加中断请求信号,因此中断的发生不是随机的而是由程序安排好的。软中断是一种推后执行的机制

操作系统为了提高中断的处理效率,一般当中断发生的时候,硬中断处理那些短时间,就可以完成的工作,而将那些比较耗时的任务,放到中断之后来完成,也就是软中断来完成

中断控制器

中断控制器是计算机系统中的一个重要组成部分,**用于管理和控制中断请求。**常见的中断控制器有Intel 8259A芯片,我们简单了解一下这个芯片:

Intel处理器允许256个中断,中断号的范围是0~2558259A负责提供其中的15个,但中断号并不固定,允许软件根据自己的需要灵活设置中断号,以防止发生冲突。该中断控制器芯片有自己的端口号,可以像访问其他外部设备一样用in和out指令来改变它的状态,包括各引脚的中断号。所以又被称为可编程中断控制器PIC

上图来源于百度百科

一个8259A芯片的组成可以分为5个主要的逻辑控件:中断屏蔽寄存器(IMR)、中断请求寄存器(IRR)、优先级仲裁单元(PR)、中断向量寄存器(ISR)和控制逻辑单元(Control Logic)

一个8259A芯片有IRQ0~IRQ7七个IRQ引脚,一个IRQ对应着一个中断号,一个中断号对应着一个中断向量,一个中断向量对应着一个中断处理子程序(ISR,Interrupt Service Routine)

8259A只适合单CPU的情况,为了充分挖掘SMP体系结构的并行性,能够把中断传递给系统中的每个CPU至关重要。Intel引入了一种名为I/O高级可编程控制器的新组件,来替代老式的8259A可编程中断控制器-高级可编程中断控制器(APIC),大家感兴趣地自行去了解一下

陷阱、故障和终止

我们再回到上文的异常这块,来了解一下X86下常见异常的类别:陷阱、故障和终止

  1. 陷阱trap:是有意的异常,一般用来在用户态和内核态之间提供系统调用接口,陷阱是同步异常,是执行一条指令的结果;陷阱程序总返回到当前指令的下一条指令,比如C语言中的printf函数,底层的实现中会有一条int 0x80指令,就是陷阱,即使用0x80号中断实现系统调用

  2. 故障fault:是由错误引起,但它可能被故障处理程序修正,故障是同步的,如果修正成功,将返回到当前正在执行的指令,CPU重新执这条指令,否则将终止故障程序。

典型的一种故障,比如缺页异常:当程序试图访问已映射在虚拟地址空间中,但是并未被加载在物理内存中的一个分页时,由中央处理器的内存管理单元所发出的中断。但缺页异常是可以被修正的,有着专门的缺页处理程序,根据缺页中断的不同类型会进行不同的处理

  1. 终止abort:由不可恢复错误引起,会直接终止程序;终止是同步的,结束时不会返回任何指令即不会将控制返回给原程序

中断异常的优先级

本文到现在我们也介绍了许多中断和异常,他们之间也是有优先级的,我们这里Intel的开发手册为例

我们接下来看看操作系统是如何处理中断的?

中断向量表 IVT

不同的中断信号,需要用不同的中断处理程序来处理。当CPU检测到中断信号后,会根据中断信号的类型去查询“中断向量表”,以此来找到相应的中断处理程序在内存中的存放位置。

中断向量表就是存放中断号和中断处理函数入口地址的表,结构类似数组,我们这里以Linux0.12为例,来看看其是如何实现中断机制的:

实模式下,16位的中断机制依赖的是中断向量表(IVT,Interrupt Vector Table),中断向量表初始化在0x0000处,位置是固定的,IVT由 BIOS程序所使用,定义了256种中断的入口地址,包括16位段地址和16位段内偏移量,其中将0到31保留用于异常处理和不可屏蔽中断。

256种中断如下:0-19的中断向量对应于异常和非屏蔽中断。
20-31Intel保留
32-127可屏蔽硬件中断
128用于系统调用的可编程异常
129-238可屏蔽硬件中断
239本地APIC时钟中断
240本地APIC高温中断
241-250由Linux留作将来使用
251-253处理器间中断
254本地APIC错误中断
255本地APIC伪中断(CPU屏蔽某个中断时产生的)

当中断发生时,处理器要么自发产生一个中断向量,要么从** int n**指令中得到中断向量,或者从外部的中断控制器接受一个中断向量。接着该向量作为索引访问中断向量表,寻找对应的中断处理程序入口地址(中断处理函数的地址为=中断向量表地址 + 4 * n),去执行程序

中断描述符表IDT

IDT,Interrupt Descriptor Table,即中断描述符表,和GDT类似,记录着0~255的中断号和调用函数之间的关系,与中段向量表有些相似,但要包含更多的信息。

其中每一个表项叫做中断描述符或门描述符(gate descriptor),的含义是指当中断发生时,必须先通过这些门,然后才能进入相应的处理程序

除了我们非常熟悉的中断描述符,IDT内还可以存放2种描述符:任务门描述符,陷阱门描述符

这些参数大家了解一下就行

  1. 中断门Interrupt Gate:中断门包含段选择符和中断或异常处理程序的段内偏移量。当控制权转移到一个适当的段时,处理器清IF标志,从而关闭将来会发生的可屏蔽中断,以避免嵌套中断的发生。中断门中的DPL(Descriptor Privilege Level)为0,因此,用户态的进程不能访问Intel的中断门。所有的中断处理程序都由中断门激活,并全部限制在内核态

什么叫中断嵌套?除了同种中断,linux任何一个新的硬中断都可以打断正在执行的中断,形如嵌套;软中断无法嵌套,但相同类型的软中断可以在不同CPU上并行执行

  1. 陷阱门Trap Gate:与中断门类似,其唯一的区别是,控制权传递到一个适当的段时处理器不修改IF标志,即不关中断;一般中断门用于处理中断,而陷阱门用来处理异常

  2. 任务门Task Gate:段选择符中存放的是任务状态段 TSS(Task State Segment)的选择子,当中断信号发生时,必须取代当前进程的那个进程的TSS选择符存放在任务门中

实模式下,16位的中断机制依赖的是中断向量表,中断向量表初始化在0x0000处,位置是固定的。为了让操作系统的代码中的逻辑地址和实际物理地址一致,操作系统启动时会把system模块搬到零地址处,这样中断向量表就会被覆盖

而在保护模式下,中断机制用的是中断描述符表IDT,位置是不固定的,设计操作系统时可以灵活设置,只需最后把其地址赋值给CPU中的IDTR寄存器。中断描述符表寄存器IDTR是一个48位的寄存器,其低16位保存中断描述符表的大小,高32位保存IDT的基址。

当中断发生时,CPU获取到中断向量后,通过IDTR的值,去查找IDT中断描述符表,得到相应的中断描述符,再根据中断描述符记录的信息来作权限判断,运行级别转换,最终调用相应的中断处理程序

IDT这个我们应该非常熟悉了,之前的文章中频繁出现,我们再来回顾一下IDT中的中断有哪些:

操作系统中的中断机制

通常在操作系统中,中断一般的处理流程如下:

  1. 外设 将中断信号发送给中断控制器8259A
  2. 8259A中优先级裁决器PR根据中断优先级,有序地将中断传递给 CPU
  3. CPU 中止执行当前程序流,将 CPU 所有寄存器的数值保存到栈中
  4. CPU 根据中断向量,从中断向量表IDT中查找中断处理程序的入口地址,继而执行中断处理程序(期间还要检查IDT表中门描述符的DPL,以保证当前程序有权限使用中断服务程序)
  5. CPU 恢复寄存器中的数值,返回原程序流停止位置继续执行

笔者再结合操作系统相关的知识,吐血画了张图,帮助大家更加直观地了解中断流程:

需要注意的是,中断前后,进程的上下文的保存与恢复,上图不是很详细,但这部分我们其实在前一篇文章Linux0.12内核源码解读(7)-陷阱门初始化介绍过:

linux调用中断函数的流程:

linux0.12对应上下文保存与恢复的源码:

.globl _divide_error,_debug,_nmi,_int3,_overflow,_bounds,_invalid_op//.globl xx表示将符号标记为一个全局符号,以供其他文件访问!!!
.globl _double_fault,_coprocessor_segment_overrun
.globl _invalid_TSS,_segment_not_present,_stack_segment
.globl _general_protection,_coprocessor_error,_irq13,_reserved
.globl _alignment_check_divide_error:pushl $_do_divide_error # 首先把将要调用的函数地址入栈;_do_divide_error是C函数do_divide_error被编译后的名字
no_error_code:# 保存被中断的进程的上下文xchgl %eax,(%esp) #_do_divide_error的地址→eax,eax被交换入栈pushl %ebxpushl %ecxpushl %edxpushl %edipushl %esipushl %ebppush %ds           # 16 位的段寄存器入栈后也要占用 4 个字节push %espush %fspushl $0		   # "error code",将数值 0 作为出错码入栈lea 44(%esp),%edx  # 取有效地址,即栈中原调用返回地址处的栈指针位置pushl %edx         # 并压入堆栈(即esp0 指针入栈)# 所有段寄存器都设置为内核数据段选择符,设置好数据寻址的基址movl $0x10,%edx    # 初始化段寄存器ds、es和fs,加载内核数据段选择符mov %dx,%dsmov %dx,%esmov %dx,%fscall *%eax         #* 号表示调用操作数指定地址处的函数,称为间接调用,这里就是执行C语言函数do_divide_error# 恢复被中断进程的上下文addl $8,%esppop %fspop %espop %dspopl %ebppopl %esipopl %edipopl %edxpopl %ecxpopl %ebxpopl %eax          # 弹出原来eax中的内容iret               # 返回中断处理之前的程序,继续执行后续指令

全文完,感谢您的阅读,如果我的文章对你有所帮助的话,还请点个免费的,你的支持会激励我输出更高质量的文章,感谢!


作者:小牛呼噜噜 ,首发于公众号 小牛呼噜噜,系列文章还有:

  1. 聊聊x86计算机启动发生的事?
  2. Linux0.12内核源码解读(2)-Bootsect.S
  3. Linux0.12内核源码解读(3)-Setup.S
  4. 图解CPU的实模式与保护模式
  5. Linux0.12内核源码解读(5)-head.s
  6. Linux0.12内核源码解读(6)-main.c
  7. Linux0.12内核源码解读(7)-陷阱门初始化
  8. 图解计算机中断
  9. Linux0.12内核源码解读(9)-blk_dev_init和chr_dev_init
  10. 什么是系统调用机制?结合Linux0.12源码图解

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/825131.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Element——组件

element官网 https://element.eleme.cn/#/zh-CN/component/layout vscode格式化快捷键&#xff1a;shiftaltf table表格 <template><el-table:data"tableData"style"width: 100%"><el-table-columnprop"date"label"日期…

Git使用总结(不断更新中)

branch 本地分支操作 删除本地分支 git branch -d <local-branch-name>远端分支操作 从远端分支创建本地分支 git checkout -b <local-branch-name> origin/<remote-branch-name>git ignore 如果工程的代码文件中有不希望上传到远端的文件&#xff0c;…

排列特征重要性(Permutation Feature Importance)

5个条件判断一件事情是否发生&#xff0c;每个条件可能性只有2种&#xff08;发生或者不发生&#xff09;&#xff0c;计算每个条件对这件事情发生的影响力。排列特征重要性模型的程序。 例一 在机器学习领域&#xff0c;排列特征重要性&#xff08;Permutation Feature Impor…

【honggfuzz学习笔记】honggfuzz的基本特性

本文架构 1.动机2.honggfuzz的基本概念官网描述解读 3. honggfuzz的反馈驱动(Feedback-Driven)软件驱动反馈&#xff08;software-based coverage-guided fuzzing&#xff09;代码覆盖率代码覆盖率的计量单位 代码覆盖率的统计方式 硬件驱动反馈&#xff08; hardware-based co…

CTFHUB RCE作业

题目地址&#xff1a;CTFHub 完成情况如图&#xff1a; 知识点&#xff1a; preg_match_all 函数 正则匹配函数 int preg_match_all ( string $pattern , string $subject [, array &$matches [, int $flags PREG_PATTERN_ORDER [, int $offset 0 ]]] )搜索 subject 中…

【Python小游戏】植物大战僵尸的实现与源码分享

文章目录 Python版植物大战僵尸环境要求方法源码分享初始化页面&#xff08;部分&#xff09;地图搭建&#xff08;部分&#xff09;定义植物类 &#xff08;部分&#xff09;定义僵尸类&#xff08;部分&#xff09;游戏运行入口 游戏源码获取 Python版植物大战僵尸 已有的植…

【Proteus】51单片机对直流电机的控制

直流电机&#xff1a;输出或输入为直流电能的旋转电机。能实现直流电能和机械能互相转换的电机。把它作电动机运行时是直流电动机&#xff0c;电能转换为机械能&#xff1b;作发电机运行时是直流发电机&#xff0c;机 械能转换为电能。 直流电机的控制&#xff1a; 1、方向控制…

动态多目标测试函数DF1-DF14,FDA1-FDA5,SDP1-SDP12的TurePOF(MATLAB代码)

动态多目标测试函数FDA1、FDA2、FDA3、FDA4、FDA5的turePOF&#xff08;MATLAB代码&#xff09; 动态多目标测试函数DF1-DF14的turePOF变化&#xff08;提供MATLAB代码&#xff09; 动态多目标测试函数SDP1-SDP12的TurePOF变化视频&#xff08;含MATLAB代码及参考文献&#xff…

Java Swing制作大鱼吃小鱼魔改版本

《大鱼吃小鱼》这款游戏的历史渊源可以追溯到休闲游戏的兴起和发展。在游戏的早期发展阶段&#xff0c;开发者们开始探索各种简单而有趣的游戏玩法&#xff0c;以吸引玩家的注意力。在这样的背景下&#xff0c;《大鱼吃小鱼》应运而生&#xff0c;它结合了自然界的食物链原理与…

AI大模型之idea通义灵码智能AI插件安装方式

问题描述 主要讲述如何进行开发工具 idea中如何进行通义灵码的插件的安装解决方案 直接在idea的plugin市场中安装 下载插件之后进行安装 见资源

lua 光速入门

文章目录 安装注释字符串变量逻辑运算条件判断循环函数Table (表)常用全局函数模块化 首先明确 lua 和 js Python一样是动态解释性语言&#xff0c;需要解释器执行。并且不同于 Python 的强类型与 js 的弱类型&#xff0c;它有点居中&#xff0c;倾向于强类型。 安装 下载解释…

【OpenHarmony】TDD-FUZZ环境配置

零、参考 1、AttributeError: ‘ElementTree‘ object has no attribute ‘getiterator‘&#xff1a;https://blog.csdn.net/suhao0911/article/details/110950742 一、创建工作目录 1、新建工作目录如&#xff1a;D:\0000_TDD_FUZZ\0000_ohos_tdd_fuzz。 2、gitee上下载 t…

陇剑杯 ios 流量分析 CTF writeup

陇剑杯 ios 流量分析 链接&#xff1a;https://pan.baidu.com/s/1KSSXOVNPC5hu_Mf60uKM2A?pwdhaek 提取码&#xff1a;haek目录结构 LearnCTF ├───LogAnalize │ ├───linux简单日志分析 │ │ linux-log_2.zip │ │ │ ├───misc日志分析 │ │…

html+vue编写分页功能

效果&#xff1a; html关键代码&#xff1a; <div class"ui-jqgrid-resize-mark" id"rs_mlist_table_C87E35BE"> </div><div class"list_component_pager ui-jqgrid-pager undefined" dir"ltr"><div id"pg…

Linux编辑器-vim的使用

vim的基本概念 vim的三种模式(其实有好多模式&#xff0c;目前掌握这3种即可),分别是命令模式&#xff08;command mode&#xff09;、插 入模式&#xff08;Insert mode&#xff09;和底行模式&#xff08;last line mode&#xff09;&#xff0c;各模式的功能区分如下&#…

中医优势病种诊疗方案数据库

中医诊疗方案结合了几千年的实践经验与理论体系&#xff0c;形成了一套独特的诊疗方法。随着国家对中医药事业的重视&#xff0c;多个中医诊疗方案被国家卫生健康委员会和国家中医药管理局等权威机构正式发布&#xff0c;这对规范中医临床诊疗行为&#xff0c;提升医疗服务质量…

执行npm命令一直出现sill idealTree buildDeps怎么办?

一、问题 今天在运行npm时候一直出项sill idealTree buildDeps问题 二、 解决 1、先删除用户界面下的npmrc文件&#xff08;注意一定是用户C:\Users\{账户}\下的.npmrc文件下不是nodejs里面&#xff09;&#xff0c;进入到对应目录下&#xff0c;Mac启动显示隐藏文件操作&…

生产服务器变卡怎么排查

服务器变卡怎么排查&#xff0c;可以从以下四个方面去考虑 生产服务器变卡怎么排查 1、网络2、cpu的利用率3、io效率4、内存瓶颈 1、网络 可以使用netstat、iftop等工具查看网络流量和网络连接情况&#xff0c;检查是否网络堵塞、丢包等问题 2、cpu的利用率 1、用top命令定…

驱动执行篇之电机编码器:编码器基础与双编码器方案

目录 |1.编码器概述 |2.编码器分类 |2.1.增量式编码器和绝对值编码器 |2.2.光电编码器 |3.双编码器方案 |3.1几种扭矩感知方案 |3.3双编码器安装方式 |1.编码器概述 编码器 编码器&#xff0c;是将信号&#xff08;如比特流&#xff09;或数据进行编制、转换为可用以通讯…

ECA-Net:深度卷积神经网络中的高效通道注意力机制【原理讲解及代码!!!】

ECA-Net&#xff1a;深度卷积神经网络中的高效通道注意力机制 在深度学习领域&#xff0c;特别是在深度卷积神经网络&#xff08;DCNN&#xff09;中&#xff0c;注意力机制已经成为提升模型性能的关键技术之一。其中&#xff0c;ECA模块&#xff08;Efficient Channel Attent…