Linux中对中断的支持

Linux内核中使用的门是在i386平台的门的基础上做了更进一步的细化后形成的,如下所示:

  1、中断门:处理器中DPL被设置为0的中断门,不能用户态下对其进行访问。Linux下所有的(硬)中断处理程序都是在核心态下通过中断门来激活的。

  2、系统门:处理器中DPL被设置为3的陷阱门,可以在用户态下对其进行访问。Linux的三种异常处理函数(中断号为4、5、128)都是通过系统门来调用的,即指令into、bound和int $0x80可以在用户态下被执行。

  3、系统中断门:处理器中DPL被设置为3的中断门,可以在用户态下访问。Linux中中断向量号为3的中断(int3)是通过系统中断门来调用的,可在用户态下被执行。

  4、陷阱门:处理器中DPL被设置成0的陷阱门,不能在用户态下进行访问。Linux中的大多数异常处理函数都是通过陷阱门被激活的。

  5、任务门:处理器中DPL被设置成0的任务门,不能在用户态下进行访问。Linux中仅有“Double Fault”异常的处理函数是通过任务门进行调用的。

  在系统引导的过程中,内核调用/arch/i386/kernel/traps.c文件中的trap_init函数来对中断进行初始化。该函数通过调用同一文件下的set_trap_gate等多个函数来对中断描述符进行初始化。

  set_trap_gate等函数的本质是调用include/asm-i386/desc.h文件中的_set_gate函数来完成对中断描述符的初始化工作,该函数的代码如下:
QUOTE:  
static inline void _set_gate(int gate, unsigned int type, void *addr, unsigned short seg)
{
__u32 a, b;
pack_gate(&a, &b, (unsigned long)addr, seg, type, 0);
write_idt_entry(idt_table, gate, a, b);
}
 

  其中,pack_gate函数的代码如下:
QUOTE:  
static inline void pack_gate(__u32 *a, __u32 *b,
unsigned long base, unsigned short seg, unsigned char type, unsigned char flags)
{
*a = (seg << 16) | (base & 0xffff);
*b = (base & 0xffff0000) | ((type & 0xff) << 8) | (flags & 0xff);
}
 

  write_idt_entry宏展开后代码如下:
QUOTE:  
#define write_idt_entry(dt, entry, a, b) write_dt_entry(dt, entry, a, b)


static inline void write_dt_entry(void *dt, int entry, __u32 entry_a, __u32 entry_b)
{
__u32 *lp = (__u32 *)((char *)dt + entry*8);
*lp = entry_a;
*(lp+1) = entry_b;
}
 

  其中,pack_gate函数的主要工作是设置相应的中断描述符,a为低32位,b为高32位。write_idt_entry的工作则是将在pack_gate函数中设置好的中断描述符填入到中断描述符表的相应位置。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wzwxfs.html