Linux中断

X86 CPU硬件对中断的支持:

        中断分为外部硬件中断、软件INT n的陷进,还有一种称为异常,比如除以0.
        中断发生时必须通过中断向量表IDT,指针存放在寄存器IDTR里,intel称为“门”gate,有四种门,任务门、中断门、陷阱们、调用门。所谓的门跟之前的段差不多,就是8字节64位的空间。
任务门:
        有P标志(1在内存中,0不在),DPL(描述优先级别),3位类型码(101代表是任务门),还有16位TSS段(任务状态段)选择码。
首先中断发生后,在中断向量表中找相应项,如果是任务门,且通过的优先级检查,就把当前的进程的TSS保存起来,
再根据任务门的TSS选择码从GDT/LDT找到需要切换的任务的TSS并装载切换任务。
        TR寄存器用来保存当前任务的TSS,但是linux内核不采用以上方式切换任务。
       
其余三种门结构类似:
        有P标志,DPL, 类型码(110中断,111陷阱,100调用), 还有D标志(1=32位,0=16位) ,段选择码,还有高16位和低16位的位移。     
中断门会在进入后把EFLAGS寄存器的IF置位,防止中断嵌套,陷阱门不会这么做。
       
        代码描述项类似段寄存器,是一个偏移(下标),在GDT(linux只用GDT)中找到相应段描述项,再根据偏移计算出中断服务程序的地址(在代码段中)。
        当cpu通过中断门找到代码段描述项,转入相应服务程序时,他的DPL会保存起来作为CPU的运行级别,从而实现保护模式。
   
        当INT指令产生中断后,先通过级别检查,低于等于当前CPU的运行级别才会产生中断。
中断时,把EFLAGS寄存器内容和CS/EIP压栈,异常的话错误码也压栈。
如果优先级低于当前的运行级别,CPU根据TR寄存器找到当前TSS,获取里面的对应级别的堆栈指针,替换老堆栈(替换SS和ESP),
并把老堆栈的指针压入新对战。
       

 

linux 中断

      首先初始化IDT,19个陷阱门,和系统固定的门,其他的门是许多队列,由irq_desc[]数组保存,该数组保存irq_desc_t类型的结构体。
数组的每一位保存一种主中断的链表,终端发生时,先执行总服务程序,再根据具体子设备号到所属队列里找特定服务程序。
        其他的存在interrupt[]的函数指针数组,数组的每一位保存相应的处理函数指针。
每个函数都差不多,主要是有2行:
pushl    $0x01-256
jmp    common_interrupt
可以看到所有中断都会先调用同一函数common_interrupt,只不过参数不同,这跟上面说的相符。
        irq_desc_t里有一个action函数列表用于控制该irq,例如enable、disable、ack、end等。
   
        使用request_irq()函数来注册中断服务(设备驱动一般都要通过此函数注册中断服务),注册后分配一个irqaction结构体,再调用setup_irq()函数来链入到中断请求队列。
中断服务号IRQX与中断向量不一样,IRQ0等于中断向量0x20
中断处理过程:
1、当CPU处于用户态运行时,中断到来,CPU从中断控制器(例i8259)取得中断向量,
2、根据中断向量从IDT里取到对应的中断门,根据中断门找到服务程序入口,这时候中断屏蔽标志已经置位了,CPU不能再响应其他中断。
3、中断服务程序属于内核,运行级别DPL为0,所以CPU从TR寄存器所指向的TSS里取得当前进程的内核堆栈(前面说了,TSS有2个堆栈,一个是用户态,一个系统态)
4、先到common_interrupt里做通用处理,主要是把寄存器入栈。系统状态的堆栈就是从物理地址0开始。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值