Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Linux内核19-中断描述符表IDT的初始化

Linux内核19-中断描述符表IDT的初始化

作者头像
Tupelo
发布于 2022-08-15 07:49:56
发布于 2022-08-15 07:49:56
96500
代码可运行
举报
文章被收录于专栏:嵌入式ARM和Linux嵌入式ARM和Linux
运行总次数:0
代码可运行

至此,我们已经理解了X86架构如何在硬件层面如何处理中断和异常,那么接下来,我们看看Linux内核管理这些中断和异常。

同所有的设备一样,我们在使能硬件之前,必须先初始化其相关的数据结构。而Linux使用中断描述符表IDT记录管理所有的中断和异常。那么,首先,Linux内核应该把IDT的起始地址写入idtr寄存器,然后初始化所有的表项。这一步在初始化系统时完成。

因为汇编指令int允许用户进程发送任意编号的中断(0-255)。为此,IDT的初始化必须考虑阻止由用户进程int指令引发的非法中断和异常。可以通过将中断描述符表中的DPL域设为0来实现。如果用户进程试图发送非法中断信号,CPU控制单元比较CPL和DPL的值,发出常规保护的异常。

但是,大部分时候,用户态进程必须能够发送可编程异常。那么把相应的中断或陷阱门描述符的DPL域设为3即可。比如系统调用。

让我们看看Linux如何实现这种策略。

中断、陷阱和系统门

在之前的文章中,我们已经介绍过,Intel提供了三种类型的中断描述符:任务,中断和陷阱门描述符。Linux的分类有些不同,它们如下所示:

  1. 中断门 和Intel的中断门相同。所有的用户进程不能访问(该门的DPL设为0)。所有Linux的中断处理程序都是通过中断门激活的,也就是说只能在内核态访问。
  2. 系统门 属于Intel的陷阱门,可以被用户态进程访问(该门的DPL设为3)。三个Linux异常处理程序对应的中断号分别是4、5和128,分别使用intoboundint $0x80三条汇编指令发出对应的中断信号。
  3. 系统中断门 属于Intel的中断门,用户态进程可以访问(该门的DPL域设为3)。中断号为3的异常处理程序通过系统中断门激活,可以使用在用户态使用int3指令实现。
  4. 陷阱门 属于Intel陷阱门,不能被用户态程序访问(该门的DPL设为0)。用来访问大部分的异常处理程序。
  5. 任务门 属于Intel任务门,用户态进程不能访问(该门的DPL设为0)。专门访问处理Double fault异常的处理程序。

对应上面的5种分类,分别有相应的函数可以初始化IDT(这些函数与硬件架构息息相关),如下所示:

  • set_intr_gate(n,addr) 插入中断门。该门内的端选择器设为内核态代码所在的段。Offset被设为addr,就是中断处理程序的地址。DPL域设为0。
  • set_system_gate(n,addr) 插入系统门。其余描述与上面的函数相同。
  • set_system_intr_gate(n,addr) 插入系统中断门。该门内的端选择器设为内核态代码所在的段。Offset被设为addr,就是异常处理程序的地址。DPL域设为3。
  • set_trap_gate(n,addr) 插入陷阱门,DPL被设为3。其余与上面函数相同。
  • set_task_gate(n,gdt) 插入任务门。段选择器设为要执行的函数所在的段。Offset设为0,而DPL设为3。

IDT第一次初始化

其实,IDT被初始化两次。第一次是在BIOS程序中,此时CPU还工作在实模式下。一旦Linux启动,IDT会被搬运到RAM的受保护区域并被第二次初始化,因为Linux不会使用任何BIOS程序。

IDT结构被存储在idt_table表中,包含256项。idt_descr变量存储IDT的大小和它的地址,在系统的初始化阶段,内核用来设置idtr寄存器,专用汇编指令是lidt。

内核初始化的时候,汇编函数setup_idt()用相同的中断门填充idt_table表的所有项,都指向ignore_int()中断处理函数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
setup_idt:
    lea ignore_int, %edx
    movl $(__KERNEL_CS << 16), %eax
    movw %dx, %ax           /*  = 0x0010 = cs */
    movw $0x8e00, %dx       /* 中断门,DPL=0 */
    lea idt_table, %edi     /* 加载idt表的地址到寄存器edi中 */
    mov $256, %ecx
rp_sidt:
    movl %eax, (%edi)       /* 设置中断处理函数 */
    movl %edx, 4(%edi)      /* 设置段描述符 */
    addl $8, %edi           /* 跳转到IDT表的下一项 */
    dec %ecx                /* 自减 */
    jne rp_sidt
    ret

中断处理函数ignore_int(),也是一个汇编语言编写的函数,相当于一个null函数,它执行:

  1. 保存一些寄存器到堆栈中。
  2. 调用printk()函数打印Unknown interrupt系统消息`。
  3. 从堆栈中恢复寄存器的内容。
  4. 执行iret指令回到调用处。

正常情况下,此时的中断处理函数ignore_int()是不应该被执行的。如果在console或者log日志中出现Unknown interrupt的消息,说明发生硬件错误或者内核错误。

完成这次IDT表的初始化之后,内核还会进行第二次初始化,用真正的trap或中断处理函数代替刚才的null函数。一旦这两步初始化都完成,IDT表就包含具体的中断、陷阱和系统门,用以控制每个中断请求。

对于IDT表的第二次初始化过程,我们将分别以异常和中断的视角分开阐述。请参考后面的文章。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-03-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 嵌入式ARM和Linux 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
中断机制和中断描述符表、中断和异常的处理
该文介绍了中断和异常的基本概念、分类,以及Linux 中中断和异常的处理方式,包括硬件中断、软件中断和异常的分类和处理。
s1mba
2017/12/28
3.9K0
中断机制和中断描述符表、中断和异常的处理
Linux内核20-Linux内核的异常处理过程
当异常发生时,Linux内核给造成异常的进程发送一个信号,告知其发生了异常。比如,如果一个进程尝试除零操作,CPU会产生除法错误异常,相应的异常处理程序发送SIGFPE信号给当前进程,然后由其采取必要的步骤,恢复还是中止(如果该信号没有对应的处理程序,则中止)。
Tupelo
2022/08/15
1.6K0
Linux内核17-硬件如何处理中断和异常
在上一篇文章中,我们已经了解了中断和异常的一些概念,对于中断和异常也有了大概的理解。那么,系统中硬件到底是如何处理中断和异常的呢?本文我们就以常见的X86架构为例,看看中断和异常的硬件工作原理。
Tupelo
2022/08/15
2.1K0
Linux内核17-硬件如何处理中断和异常
Linux中断一网打尽(1) —— 中断及其初始化
既然叫中断, 那我们首先就会想到这个中断是中断谁?想一想计算机最核心的部分是什么?没错, CPU, 计算机上绝大部分的计算都在CPU中完成,因此这个中断也就是中断CPU当前的运行,让CPU转而先处理这个引起中断的事件,通常来说这个中断的事件比较紧急,处理完毕后再继续执行之前被中断的task。比如,我们敲击键盘,CPU就必须立即响应这个操作,不然我们打字就全变成了慢动作~。说白了中断其实就是一种主动通知机制,如果中断源不主动通知,那想知道其发生了什么事情,只能一次次地轮询了,白白耗费CPU。
扫帚的影子
2020/02/25
1.7K0
Linux中断一网打尽(1) —— 中断及其初始化
Linux中断 - IDT
中断描述符表简单来说说是定义了发生中断/异常时,CPU按这张表中定义的行为来处理对应的中断/异常。
扫帚的影子
2020/02/18
6.7K0
Linux中断 - IDT
深入分析Linux内核源代码阅读笔记 第三章
中断控制是计算机发展中一种重要的技术,最初它是为克服对 I/O 接口控制采用程序查询所带来的处理器低效率而产生的。
云微
2023/02/11
1.4K0
Linux内核21-Linux内核的中断处理过程
如前所述,我们知道异常的处理还是比较简单的,就是给相关的进程发送信号,而且不存在进程调度的问题,所以内核很快就处理完了异常。
Tupelo
2022/08/15
2.5K0
Linux内核21-Linux内核的中断处理过程
中断描述符表
中断描述符表是保护模式下用于存储中断处理程序的数据结构。CPU在接收到中断时,会根据中断向量在中断描述符表中检索对应的描述符。
shysh95
2021/09/24
8360
Linux内核之旅/张凯捷——系统调用分析(1)
In computing, a system call is the programmatic way in which a computer program requests a service from the kernel of the operating system it is executed on. This may include hardware-related services (for example, accessing a hard disk drive), creation and execution of new processes, and communication with integral kernel services such as process scheduling. System calls provide an essential interface between a process and the operating system.
Linux阅码场
2019/10/08
1.6K0
Linux内核之旅/张凯捷——系统调用分析(1)
xv6(5) 中断代码部分
公众号后台回复 $interrupt$ 可获取原图,另外我说明一下我画的流程图啊,的确是不标准的,有很多环了,我有试过只画一根线比如说 $iret$ 出去一根线后,按理说不会回到 $iret$ 而是直接指向原任务那个块。但是因为整个流程图的元素太多,这样画很难看很难看,所以我没采用。虽然如上图那么画不是那么准确,但是意思表达应该还是很明确的,而且相对来说好看些。诸位有什么好的建议还请指出,谢谢。不多说废话了,来看 $xv6$ 的中断机制
rand_cs
2023/12/05
3630
操作系统内核中的初始化工作
看完了进入内核前的工作后,我网络编程课的抄写作业自然是可以圆满完成啦,不过看了一部分后觉得确实很有意思,所以也是决定继续看下去,并且计划看完linux源码后跟着MIT6.s081写一个小的操作系统内核,希望我能够在6.29之前完成这个工作哈哈也就是我开始军训之前,补军训确实是个令人苦恼的事情。
ek1ng
2022/08/10
7700
操作系统内核中的初始化工作
system_call到iret过程分析
(1)中断有两种,一种是由CPU外部硬件产生的,另一种是由CPU本身执行程序的过程中产生的;外部中断即我们所说的中断(interrupt),外部中断是异步的,由硬件产生,我们无法预测它什么时候发生; (2)x86软件产生的中断是由“INT n”同步产生的,由程序产生,只要CPU执行了一条INT指令,就知道在开始执行下一条指令前就会进入中断服务程序,我们又称此类中断为“陷阱”;int 80为系统调用的陷阱号; (3)异常,是被动的,如页面异常,除数为0的异常; 因此系统调用是中断中的陷阱的一种,系统调用只发生在用户空间,必然会发生用户栈和内核栈的切换。
De4dCr0w
2019/02/27
1.1K0
Linux 内核0.11 系统调用详解(上)
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u014688145/article/details/50608829
用户1147447
2019/05/26
1.7K0
linux0.11中断处理源码初探
所以idt的内容是一个单位是8字节,长度是256的数组。linux0.11分为中断、系统、陷阱门。系统在启动的时候设置idt。
theanarkh
2019/04/23
1.8K0
Linux内核13-进程切换
进程切换,又称为任务切换、上下文切换、或者任务调度。本文就研究Linux内核的进程切换。我们首先理解几个概念。
Tupelo
2022/08/15
2K0
Linux内核13-进程切换
系统调用(int 0x80)详解
在系统启动时,会在sched_init(void)函数中调用set_system_gate(0x80,&system_call),设置中断向量号0x80的中断描述符:
全栈程序员站长
2022/09/30
1.6K0
【linux学习指南】linux捕捉信号(二)软中断&&缺⻚中断?等&& 如何理解内核态和⽤⼾态
如果是这样,操作系统不就可以躺平了吗?对,操作系统⾃⼰不做任何事情,需要什么功能,就向中 断向量表⾥⾯添加⽅法即可.操作系统的本质:就是⼀个死循环!
学习起来吧
2024/12/30
1070
【linux学习指南】linux捕捉信号(二)软中断&&缺⻚中断?等&& 如何理解内核态和⽤⼾态
xv6(4) 中断理论部分
中断是硬件和软件交互的一种机制,可以说整个操作系统,整个架构都是由中断来驱动的。中断的机制分为两种,中断和异常,中断通常为 $IO$ 设备触发的异步事件,而异常是 $CPU$ 执行指令时发生的同步事件。本文主要来说明 $IO$ 外设触发的中断,总的来说一个中断的起末会经历设备,中断控制器,$CPU$&$OS$ 三个阶段:设备产生中断,中断控制器接收和发送中断,$CPU$&$OS$ 来实际处理中断。
rand_cs
2023/12/05
3710
进入Linux内核前的准备
最近看到这个github仓库flash-linux0.11-talk,觉得还算是蛮有意思的,加上网络编程的课程又有抄写一段tcp协议实现代码或者交一篇linux内核源码阅读的笔记,还是比较讨厌这种低效率的抄写的所以就想写篇文章记录一下粗浅阅读源码后的大概了解,这个github仓库作者的文章我觉得写的还是不错的对于我这类小白而言,也比较有看得下去的动力。
ek1ng
2022/08/10
5.7K0
进入Linux内核前的准备
结合中断上下文切换和进程上下文切换分析Linux内核的一般执行过程
下面从逻辑上完整走一遍中断处理过程(结合中断上下文的切换,以定时器中断为例,假设从用户态进入中断):
抖音hzcya
2020/06/13
1.4K0
相关推荐
中断机制和中断描述符表、中断和异常的处理
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验