zoukankan      html  css  js  c++  java
  • 《深入理解Linux内核》阅读笔记 --- 第四章 中断和异常

    1、中断的作用:中断信号提供了一种方式,使处理器转而去运行正常控制流之外的代码。当一个中断信号到达时,CPU必须停止它当前所做的事,并切换到一个新的活动。为了做到这一点,就要在内核态堆栈保存程序计数器的当前值(即eip和cs寄存器的内容),并把与中断类型相关的一个地址放进程序计数器。

    2、异常又分为三种类型:

    (1)、故障(Fault):保存在eip中的值是引起故障的指令地址,因此,当异常处理程序终止时,会重新执行该指令。(例如,缺页异常处理程序)。

    (2)、陷阱(Trap):保存在eip中的值是引起陷阱的指令之后的指令。主要用于调试程序。

    (3)、异常结束(Abort):发生严重错误,不能在eip中保存有意义的值。一般由硬件故障引起,只能迫使受影响的进程终止。

    3、IRQ和中断:每个能够发出中断请求的硬件设备控制器都有一个指派为IRQ(Interrupt ReQuest)的输出线。所有现有的IRQ线都与一个叫做中断控制器的硬件电路的输入引脚相连,中断控制器执行以下动作:

    1. 监视IRQ线,检查产生的信号
    2. 如果在IRQ线上产生一个信号:
      1. 把接收到的信号转换成一个对应的向量
      2. 把这个向量存放在中断控制器的I/O端口,从而允许CPU通过数据总线读此向量
      3. 把产生的信号发送到处理器的INTR引脚,即发出一个中断
      4. 等待,直到CPU确认这个中断信号,把它写进可编程中断控制器(PIC)的其中的一个IO端口,同时,清INTR线

      3. 返回第一步

    4、被禁用的中断是丢失不了的,它们一旦变为允许,PIC就又把被禁用的中断发送到CPU。这个特点被大多数中断处理程序所使用,因为这允许中断处理程序连续地处理同一类型的IRQ。

    5、当eflags寄存器的IF标志被清除时,由PIC发布的可屏蔽中断被CPU临时忽略。cli和sti汇编指令分别清除和设置该标志。

    6、中断描述符表(Interrupt Descriptor Table,IDT)包含了三种类型的描述符:任务门(Task gate),中断门(Interrupt gate)和陷阱门(Trap gate)。中断门中包含了段选择符和一个中断或异常处理程序的段内偏移。当控制器转入一个适当的段时,处理器清IF标志,从而关闭接下来会发生的可屏蔽中断。Linux用中断门处理中断,用陷阱门处理异常。

    7、当发生中断或异常时,控制单元将:

    1. 根据中断或异常的向量i,访问idtr和gdtr寄存器,找到中断或异常处理程序所在段的基地址和偏移。
    2. 权限检查,要求中断处理程序的特权不能低于引起中断的程序的特权,即gdtr指向的段描述符的DPL不能大于CPL。如果是编程异常,则要求处于IDT中的门描述符的DPL要小于CPL,这能防止用户应用进程访问特殊的陷阱门或中断门。
    3. 若发生了特权级的变化,控制单元必须开始使用与新的特权级相关的栈,通过访问当前进程的TSS段,获取正确的ss和esp值,并且在新的栈中保存ss和esp以前的值。
    4. 如果故障已经发生,则用引起异常的指令地址装载cs和eip,从而使得该指令能再次被执行。保存eflag, cs以及eip的内容,如果异常产生了一个硬件错误码,将它保存在栈中。
    5. 根据IDT表中的第i项门描述符的段选择符和偏移装载cs和eip

    中断或异常被处理完成之后,相应的处理程序必须产生一条iret指令,把控制权转交给被中断的进程,这将导致控制单元:

    1. 用堆栈中的值装载cs, eip和eflag,如果一个硬件错误码被压入栈中,并且在eip内容的上面,那么在执行iret指令前必须先弹出这个硬件错误码。
    2. 检查处理程序的CPL是否等于cs中的最低两位的值。如果是,iret终止执行,否则转入下一步
    3. 从栈中装载ss和esp,返回到与旧特权级相关的栈。
    4. 检查ds,es,fs和gs段寄存器的内容,如果其中的一个寄存器包含的选择符是一个段描述符,并且其DPL小于CPL,那么清相应的段寄存器。这么做的原因是防止用户态的程序利用内核以前使用的段寄存器来访问内核地址空间。

     8、当CPU正在执行一个与中断有关的内核控制路径时,Linux的设计不允许发生进程切换。但是,这样的内核控制路径可以随意嵌套,即一个中断处理程序可以由另一个中断处理程序进行中断。

    9、当一个中断处理程序正在运行时,相应的IRQ线上再发出的信号就被忽略。更重要的是中断处理程序是代表进程执行的,它所代表的进程必须总处于TASK_RUNNING状态,否则可能出现系统僵死情形,并且中断处理程序不能执行任何阻塞过程。

    10、所有的中断处理程序执行四个相同的基本操作:

    1. 在内核态堆栈中保存IRQ的值和寄存器的内容
    2. 为正在给这个IRQ线服务的PIC发送一个应答,这将允许PIC进一步发出中断
    3. 执行共享这个IRQ的所有设备的中断服务例程(ISR)
    4. 跳到ret_from_intr()的地址后终止

    -----------------------------------------------------------------补充-----------------------------------------------------

    1、In order to ensure that these protected control transfers are actually protected, the processor's interrupt/exception mechanism is designed so that the code currently running when the interrupt or exception occurs does not get to choose arbitrarily where the kernel is entered or how.

    2、The Task State Segment.When an x86 processor takes an interrupt or trap that causes a privilege level change from user to kernel code, it also switches to a stack in the kernel's memory.A structure called the task state segment(TSS) specifies the segment selector and address where this stack lives.The processor pushes (on the new stack)SS, ESP, EFLAGS, CS, EIP, and an optional error code.Then it loads the CS and EIP from the interrupt descriptor, and sets the ESP and SS to refer to the new stack.

    3、Nested Exceptions and Interrupts.只有当从用户态进入内核态时,x86处理器才会自动切换stack,并压入old registers以及调用IDT中指定的exception handler。当处理器已经处于内核态时,CPU并不切换stack,只是将必要的内容入栈。

  • 相关阅读:
    python 数据结构与算法之排序(冒泡,选择,插入)
    python 面向对象基础和高级复习
    python numpy模块
    高精度算法
    数论
    位运算和时间复杂度的分析
    C++ OI图论 学习笔记(初步完结)
    C++语言入门知识点(详细版)【持续更新每周三更】,小舒舒戳这里!!!
    C++基础语言知识大汇总(不断更新!!!)
    二分
  • 原文地址:https://www.cnblogs.com/YaoDD/p/6381256.html
Copyright © 2011-2022 走看看