Linux内核:中断 - IDT中断描述符表

本文详细介绍了Linux内核中的中断描述符表(IDT),包括如何设置IDT、中断描述符项定义、IDT中断描述符表的存储以及硬件中断的实现和调用流程。通过理解IDT,可以更好地了解Linux内核处理中断和系统调用的方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如何设置IDT

IDT 中断描述符表定义

中断描述符表简单来说说是定义了发生中断/异常时,CPU按这张表中定义的行为来处理对应的中断/异常。

#define IDT_ENTRIES         256
gate_desc idt_table[IDT_ENTRIES] __page_aligned_bss;

从上面我们可以知道,其包含了256项,它是一个gate_desc的数据,其下标0-256就表示中断向量,gate_desc我们在下面马上介绍。

中断描述符项定义

  • 当中断发生,cpu获取到中断向量后,查找IDT中断描述符表得到相应的中断描述符,再根据中断描述符记录的信息来作权限判断,运行级别转换,最终调用相应的中断处理程序;
  • 这里涉及到Linux kernel的分段式内存管理,我们这里不详细展开,有兴趣的同学可以自行学习。如下简述之:
  1. 我们知道CPU只认识逻辑地址,逻辑地址经分段处理转换成线性地址,线性地址经分页处理最终转换成物理地址,这样就可以从内存中读取了;
  2. 逻辑地址你可以简单认为就是CPU执行代码时从CS(代码段寄存器) : IP (指令计数寄存器)中加载的代码,实际上通过CS可以得到逻辑地址的基地址,再加上IP这个相对于基地址的偏移量,就得到真正的逻辑地址;
  3. CS寄存器16位,它不会包含真正的基地址,它一般被称为段选择子,包括一个index索引,指向GDT或 LDT的一项;一个指示位,指示index索引是属于GDT还是LDT; 还有CPL, 表明当前代码运行权限;
  4. GDT: 全局描述符表,每一项记录着相应的段基址,段大小,段的访问权限DPL等,到这里终于可以获取到段基地址了,再加上之前IP寄存器里存放的偏移量,真正的逻辑地址就有了。
  5. 附上简图:

idt2.jpg

  • 我们先看中断描述符的定义:
struct gate_struct {
  u16     offset_low;
  u16     segment;
  struct idt_bits bits;
  u16     offset_middle;
#ifdef CONFIG_X86_64
  u32     offset_high;
  u32     reserved;
#endif
} __attribute__((packed));

其中:

  1. offset_high,offset_middleoffset_low合起来就是中断处理函数地址的偏移量;
  2. segment就是相应的段选择子,根据它在GDT中查找可以最终获取到段基地址;
  3. bits是该中断描述符的一些属性值:
struct idt_bits {
   u16     ist : 3,
           zero    : 5,
           type    : 5,
           dpl : 2,
           p   : 1;
} __attribute__((packed));

ist表示此中断处理函数是使用pre-cpu的中断栈,还是使用IST的中断栈;

type表示所中断是何种类型,目前有以下四种:

enum {
   GATE_INTERRUPT = 0xE, //中断门
   GATE_TRAP = 0xF, // 陷入门
   GATE_CALL = 0xC, // 调用门
   GATE_TASK = 0x5, // 任务门
};

的概念这里主要用作权限控制,我们从一个区域进到另一个区域需要通过一扇门,有门禁权限才可以通过,因此 dpl就是这个权限,实际中我们

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值