中断和异常—中断描述符表的初始化

一、中断描述符表的初始化

从操作系统角度描述中断描述符表的初始化。

Linux内核在系统的初始化阶段需要进行大量的初始化工作,与中断相关的工作有:初始化可编程控制器(中断控制器)8259A;将中断描述符表的起始地址载入IDTR寄存器,并初始化表中的每一项。

用户进程通过INT指令发出一个中断请求,其中断请求向量在0~255之间。为防止用户使用INT指令模拟非法的中断和异常,必须对中断描述符表进行谨慎的初始化。其措施之一是将中断门或陷阱门中的请求特权级DPL域置为0。如果用户进程发出这样一个中断请求,CPU会检查出其当前特权级CPL(3)与所请求的特权级DPL(0)冲突,产生一个通用保护异常。

但有时必须让用户进程能够使用内核提供的功能(系统调用),从用户态进入内核态,通过把中断门或陷阱门的DPL域置为3。

当计算机运行在实模式时,中断描述符表被初始化,由BIOS使用。一旦真正进入Linux内核,中断描述符表被移到内存的另一个区域,并为进入保护模式进行预初始化:用LIDT指令对中断描述符表寄存器IDTR初始化,即把IDTR置为0。把中断描述符表IDT的起始地址载入IDTR。

用setup_idt()填充中断描述符表中的256个表项。填充这个表时,使用一个空的中断处理程序。理由因为处于初始化阶段,没有任何中断处理程序,因此,用空的中断处理程序填充每个表项。

对中断描述符表预初始化后,内核将在启用分页功能后对IDT进行第二遍初始化,即用实际的陷阱和中断处理程序替换这个空的处理程序。一旦这个过程完成,对于每个异常,IDT都有一个专门的陷阱门或系统门,对每个外部中断,IDT都包含专门的中断门。

1、IDT(中断描述符表)表项的设置(linux-2.4.x.x)

IDT表项的设置通过_set_gate()函数实现,如何调用_set_gate()函数在IDT表中插入一个门。

代码路径:arch/i386/kernel/traps.c(x86体系架构)

#define _set_gate(gate_addr,type,dpl,addr) \
do { \
  int __d0, __d1; \
  __asm__ __volatile__ ("movw %%dx,%%ax\n\t" \
        "movw %4,%%dx\n\t" \
        "movl %%eax,%0\n\t" \
        "movl %%edx,%1" \
        :"=m" (*((long *) (gate_addr))), \
         "=m" (*(1+(long *) (gate_addr))), "=&a" (__d0), "=&d" (__d1) \
        :"i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
         "3" ((char *) (addr)),"2" (__KERNEL_CS << 16)); \
} while (0)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值