当前课程知识点:Linux 内核分析与应用 >  第5章 中断 >  5.2 中断处理机制 >  Video

返回《Linux 内核分析与应用》慕课在线视频课程列表

Video在线视频

Video

下一节:Video

返回《Linux 内核分析与应用》慕课在线视频列表

Video课程教案、知识点、字幕

大家好 我们今天来开始介绍中断处理机制

那么 首先我们来看中断描述符表以及初始化

在上一讲里头呢我们介绍了中段描述符表

那么中段描述符表IDT放在什么地方呢

什么时候对它进行初始化

实际上 IDT放在内核的数据段中

它的起始地址呢放在

中段描述表寄存器(IDTR)中如图所示

那么在内核中中断描述符表相关的源代码是什么样子呢

有一个变量是IDT_DESCR变量

它存放在什么地方呢 存放在

head_32.s

或者在64位上呢叫head_64.s中

那么这里头我们有两个汇编语句

第一句表示中断描述符表呢

包含256个中断描述符

第二句呢表示中断描述符的入口地址

那么如何对中断描述符表进行初始化呢

在Linux内核中 在系统的初始化阶段要初始化可编程控制器

将中断描述符表的起始地址装入中段描述符表(IDTR)寄存器中

并且开始初始化表中的每一项

当计算机运行在实模式的时候呢

中断描述符表被初始化 并由BIOS使用

当真正进入了Linux内核以后呢 中断描述符表就被移动到内核的另一个区域

并且进入保护模式进行预初始化

那么首先我们来看一下怎么样来初始化陷阱门和系统门

对陷阱门的初始化有专门的函数叫作trap_init()函数

它用于设置中断描述符表最开始的19个陷阱门

以及包含了一个系统门

那么这些中断向量都是cpu保留用于异常处理的

在这里头我们给出了几个样例 比如说

对0号异常 1号异常和19号异常的初始化

那么如何对系统门进行初始化呢 那么系统门的编号是0x80

那么这个呢有专门的函数叫作set_system_gate来对系统门进行初始化

那么如何对中断门进行设置呢

实际上中断门的设置也有专门的函数叫作init_IRQ()函数

那么这其中的一段代码就是对中断门进行初始化

那么在中断门设置的时候呢 必须跳过用于系统调用的向量0x80

中断处理程序的入口地址是一个数组interrupt[]

数组中的每个元素是指向中断处理例程(ISR)的指针

而每个中断处理例程属于内核中的代码段

既然是内核中的代码段呢

也就是说它的段地址存放于全局描述表(GDT)中

那么整个的中断处理过程是什么样子呢

我们这里呢给出四个步骤

那么一个步骤呢就是中断和异常的硬件处理

也就是说怎么从硬件的角度如何看CPU处理中断和异常

那么第二步呢就是中断请求队列的建立

这是为了干什么呢 是为了方便外设共享中断线

第三部是中断处理程序的执行

在这里我们引入两个概念 一个叫中断处理程序 一个叫中断服务例程(ISR)

那么最后就是从中断返回

也就是调用中断线上的宏彻底从中断返回

我们看一下X86中是如何处理中断的

那么这张图呢就给出了X86的中断处理过程

首先呢 我们看就是说当cpu呢

执行了当前指令之后呢

CS和EIP这对寄存器中所包含的内容呢

就是下一条要执行指令的新地址呢

那么在对下一条指令执行之前呢

实际上CPU首先要判断

在执行当前指令的过程中是否发生了中断或异常

如果发生了一个中断或异常呢 那么CPU将做以下事情

做什么事情呢 首先确定所发生中断或异常的向量i

这个数呢在0~255之间

然后呢通过IDTR寄存器找到IDT表

读取IDT表第i项

或者呢叫第i个门

然后呢从GDTR寄存器获得GDT表的地址

结合中断描述符表中的段描述符呢

在全局描述符表中获得中断处理程序对应的段描述符

从该段描述符中呢

获得中断/异常处理程序所在的段基址

然后呢与其偏移量相加呢得到中断处理程序的入口地址

在这其中要进行“段”级"和“门”级两步有效性检查

最后还要检查是否发生了特权级的变化

那么 如果发生了特权级的变化 中断的处理过程

堆栈呢会有什么样的变化 我们来看一下

当中断发生在用户态的时候呢

也就是特权级发生了变化 它的特权级呢为三

而中断处理程序运行在内核态

它的特权级呢为0

也就是特权级发生了变化

所以呢会引起堆栈的更换

也就是说呢 要从用户堆栈切换到内核堆栈

而当中断发生在内核态时候呢

也就是CPU在内核中运行的时候呢 则不会更换堆栈

从图可以看出

当从用户态堆栈切换到内核态堆栈的时候呢

首先把用户态堆栈的值压入中断程序的内核态堆栈中

同时把 EFLAGS寄存器自动的压栈

然后把被中断进程的返回地址压入堆栈

如果异常产生了一个硬错误码呢

则将它也保存在堆栈中

如果特权级没有发生变化

则压入栈中的内容如图右边所示

前面已经得到中断处理程序的入口地址

于是呢CPU就跳转到了中断或异常处理程序

那么接着我们要讲中断请求队列是如何建立的

由于硬件条件的限制 很多硬件设备共享一条中断线的

为方便处理呢

Linux为每条中断线设置了一个中断请求队列

因此呢我们介绍四个方面的内容

首先中断处理 也就是介绍中断处理程序与中断服务例程

紧接着介绍中断共享

主要介绍中断线共享的数据结构

然后我们要注册中断服务例程

最后是注销中断服务例程

那么下面我们来看一下中断处理程序与中断服务例程

当外设发出中断请求的时候呢

通过中断控制器PIC的int引脚向CPU请求中断处理 则中断处理机制启动

其中呢 包含两个部分一个叫中断处理程序

共享同一条中断线的所有中断请求呢 有一个总的中断处理程序

那么另外一个叫中断服务例程(Interrupt Service Routine )

这是什么呢 就是每个中断请求都有自己单独的中断服务例程

下面我们来介绍中断描述符 也就是IRQ数据结构

在内核中呢 对于每一个外设的IRQ都用struct irq_desc来描述

我们把它称之中断描述符

内核中会有一个数据结构保存了关于所有IRQ的中断描述符信息 放在一个数组中

那么这个数组是Linux内核中维护IRQ资源的管理单元

它记录了某IRQ号对应的流控处理函数 中断控制器

中断服务程序 IRQ自身的属性 资源等等的信息是内核中中断子系统的一个核心数组

那么接着我们介绍中断线共享的数据结构irqaction

每个设备能共享一个单独的IRQ

因此内核要维护多个irqaction描述符

其中每个描述符涉及一个特定的硬件设备和一个特定的中断

那么在这个数据结构中呢有这么几个字段

我们看第一个字段

它就是指向一个具体I/O设备的中断服务例程

第二个字段用于标志描述符中断线与I/O设备之间的关系

第三个字段表示I/O设备名

第四个字段指定I/O设备的主设备号和次设备号

那么最后一个字段指向irqaction描述符链表的下一个元素

最后我们来看一下如何注册和注销中断服务例程

我们说中断描述符表IDT初始化后呢

必须通过 request_irq() 函数将相应的中断服务例程挂入中断请求队列中

也就是说对他进行注册

原型呢如图所示 其中呢

参数中的中断服务例程被挂入中断请求队列中

那么

当我们关闭设备的时候呢 必须通过调用free_irq()函数释放所申请的中断请求号

那么如何对中断处理程序进行执行呢 我们进行一个概要的描述

我们说CPU从中断控制器的一个端口取得中断向量I以后呢

根据I从中断描述符表IDT中找到相应的中断门

从中断门获得中断处理程序的入口地址

接着呢判断是否要进行堆栈的切换

接下来呢就会 调用do_IRQ()对所接收的中断进行应答

并禁止这条中断线上中断的发生

那么在这个过程中呢 调用一个很重要的函数叫handle_IRQ_event()函数

来运行对应的中断服务例程

关于这些源代码的分析呢 将在下一讲的动手实践中呢具体查看和分析

那么最后我们就要从中断返回

当所有的中断处理程序在处理完之后呢都要返回

那么首先要判断进入中断前是用户空间还是内核空间

如果进入中断前是内核空间的话 则直接调用 RESTORE_ALL函数

如果进入中断前是用户空间的话 则可能需要进行一次调度

如果不调度 则可能有信号需要处理

那么最后呢 还是要

从栈里头恢复所有寄存器的值

寄存器的恢复和保存呢是一个相反的操作

那么最后呢 就要调用中断返回指令 将处理权交给 CPU

从中断返回的时候呢 CPU要调用恢复中断现场的宏 彻底的恢复中断现场

关于中断 异常以及系统调用返回呢

我们可以看操作系统还做了什么 那么在这里呢 我们抛出四个问题

第一个问题内核调度与中断 异常 系统调用的关系如何

我们把中断 异常 系统调用 统称为中断

第二个问题信号处理与中断的关系如何

第三个问题内核抢占与中断的关系如何

第四个问题内核线程的调度有何特别之处

中断返回的时候呢内核线程会发生调度吗

首先看第一个问题

中断返回和异常返回的流程基本一致的

差别主要在于异常返回的时候呢 需要先关一次中断

因为Linux实现中 异常使用的是陷阱门

通过时不会自动关中断

而中断使用的是中断门 通过时会自动关闭中断

第二个问题 中断/异常包括系统调用返回的时候呢

是进行调度(schedule)的重要时机点

其中 时钟中断返回时是调度依赖的最主要的时机点

时钟中断处理函数中不会直接进行调度

只是根据相应的调度算法决定是否需要调度 以及调度的下一个任务

如果需要调度呢 则设置调度标志

调度(schedule)的实际执行是在中断返回的时候才进行的

怎么进行那它就检查一下中断标志

如果有中断标志的话则进行调度

第三个问题 信号处理是在当前进程从内核态返回用户态时进行的

在发生中断 异常(包括系统调用) 或fork的时候呢

都有可能从内核态返回用户态

这个时候呢都是处理信号的时机

在这里要注意只有当前进程的信号才能在此时得到处理

其它非正在运行的进程的信号无法处理的

那么关于内核枪占和内核线程的调度呢也是非常的有趣

那么这个问题呢就留给读者自己来思考了

最后我们要动手实践 Linux内核之旅网站的电子栏目

第八期“中断”呢向读者依次介绍了

中断的概念 解析Linux中的中断实现机理以及Linux下中断如何被使用

参考资料呢

深入理解Linux内核 第三版第四章讲的是中断

Linux内核设计与实现 第三版第七章呢 讲的也是中断

那么在蜗窝科技网站关于中断有一系列的文章

非常详细的介绍了中断的方方面面

最后呢大家带着思考离开

中断返回除了返回现场外呢

从源代码角度分析内核还做了什么

谢谢大家

Linux 内核分析与应用课程列表:

第1章 概述

-1.1 Linux操作系统概述

--1.1 Linux 操作系统概述

-1.2 Linux内核结构以及内核模块编程

--Video

-1.3 Linux内核源码中的双链表结构

--Video

-1.4 源码分析-内核中的哈希表

--Video

-1.5 动手实践-Linux内核模块的插入和删除

--Video

-第1章 概述--章节测验

-第1章导学--引领你进入Linux内核的大门

第2章 内存寻址

-2.1 内存管理之内存寻址

--Video

-2.2 段机制

--Video

-2.3分页机制

--Video

-2.4 动手实践-把虚拟地址转换成物理地址

--Video

-第2章 内存寻址--章节测验

-第二章导学-从零打造自己的操作系统

第3章 进程管理

-3.1 进程概述

--Video

-3.2 Linux进程创建

--Video

-3.3 Linux进程调度

--Video

-3.4 动手实践-打印进程描述符task_struct中的字段

--Video

-3.5工程实践-基于内核模块的负载监控

--Video

-第3章 进程管理--章节测验

-第三章导学-进程背后琳琅满目的宝贝到哪里挖?

第4章 内存管理

-4.1 Linux内存管理机制

--Video

-4.2 进程用户空间管理机制

--Video

-4.3 物理内存分配与回收机制(上)

--Video

-4.4 物理内存分配与回收机制(下)

--Video

-4.5 动手实践-Linux内存映射基础(上)

--Video

-4.6 动手实践-Linux内存映射实现(中)

--Video

-4.7 动手实践-Linux内存映射测试(下)

--Video

-4.8 初学者对内存管理的常见疑惑

--初学者对内存管理的常见疑惑(一)

--初学者对内存管理的常见疑惑(二)

--初学者对内存管理的常见疑惑(三)

-第4章 内存管理--章节测验

第5章 中断

-5.1 中断机制概述

--Video

-5.2 中断处理机制

--Video

-5.3 中断下半部处理机制

--Video

-5.4 时钟中断机制

--Video

-5.5 动手实践-中断上半部的代码分析及应用

--Video

-5.6 动手实践-中断下半部的代码分析及应用

--Video

-第5章 中断--章节测验

第6章 系统调用

-6.1 Linux中的各种API

--Video

-6.2 系统调用机制

--Video

-6.3 动手实践-添加系统调用(系统调用日志收集系统)

--Video

-第6章 系统调用--章节测验

第7章 内核同步

-7.1 内核同步概述

--Video

-7.2 内核同步机制

--Video

-7.3 动手实践-内核多任务并发实例(上)

--Video

-7.4 动手实践-内核多任务并发实例(下)

--Video

-第7章 内核同步--章节测验

第8章 文件系统

-8.1 虚拟文件系统的引入

--Video

-8.2 虚拟文件系统的主要数据结构

--Video

-8.3 文件系统中的各种缓存

--Video

-8.4 页高速缓存机制以及读写

--Video

-8.5 动手实践-编写一个文件系统(上)

--Video

-8.6 动手实践-编写一个文件系统(中)

--Video

-8.7 动手实践-编写一个文件系统(下)

--Video

-第8章 文件系统--章节测验

第9章 设备驱动

-9.1 设备驱动概述

--Video

-9.2 I/O空间管理

--Video

-9.3 设备驱动模型

--Video

-9.4 字符设备驱动程序简介

--Video

-9.5 块设备驱动程序简介

--Video

-9.6 动手实践-编写字符设备驱动程序

--Video

-9.7工程实践-编写块设备驱动的基础(上)

--Video

-9.8 工程实践-块设备驱动程序分析(中)

--Video

-9.9 工程实践-块设备驱动程序实现(下)

--Video

-第9章 设备驱动--章节测验

致谢与说明

-致谢与说明

--Video

直播视频:从Linux内核学习到自主操作系统研发

-从Linux内核学习到自主操作系统研发

附录:实验代码、课件以及相关素材

-各章实验代码

-《Linux内核分析与应用》课件

-《Linux操作系统原理与应用》教材课堂视频

Video笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。