《深入理解Linux内核》学习笔记——中断和异常

来源:互联网 发布:工作流软件是什么 编辑:程序博客网 时间:2024/06/05 22:34

Tips: Linux Kernel Based on x86 Platform


1.      异常(也称同步中断)分类:

a)        处理器探测异常,根据eip寄存器值可进一步分为:

                        i.             故障(fault):当异常处理程序终止时,eip指示的引起故障的指令将被重新执行。

                      ii.             陷进(trap):主要用于调试程序(如断点)

                     iii.             异常中止(abort):严重错误。异常处理程序将强制受影响的进程终止。

b)        编程异常(也叫软中断software interrupt):有编程者请求发生,由int或int3指令触发。


2.      中断描述符(IDT):

a)        idtr寄存器指示IDT的线性基地址及最大长度;

b)        IDT包含三种类型的描述符:

                        i.             任务门:存放取代当前进程的那个进程的TSS选择符;

                      ii.             中断门:包含中断处理函数所在段的段选择符和段内偏移量;控制权转移时,处理器清IF标志;

                     iii.             陷进门:包含异常处理函数所在段的段选择符和段内偏移量;控制权转移时,处理器不清IF标志;

3.      异常的硬件处理:

a)        确定异常向量i,读取由idtr指向的IDT表的第i个异常(或中断)描述符;

b)        根据得到的中断描述符的段选择子和gdtr内容得到异常处理程序所在段的段描述符;

c)        特权级检测:将存放在cs寄存器中的当前特权级CPL与上述过程得到的段描述符特权级(DPL)做比较;

d)        如果特权级发生变化,控制单元必须开始使用与新特权级相关的栈(主要相关寄存器为ss、esp);

e)        保存eflags、cs、eip内容及可能的错误码;

f)         用IDT第i个描述符的段选择子和偏移量分别装载cs和eip寄存器,程序控制权转移给异常处理控制路径。

注:异常处理结束后,控制单元将执行上述过程的反操作。


4.      中断描述符的初始化(在系统的启动过程中):

a)        setup()函数为内核程序的执行建立环境,将CPU从实模式切换到保护模式。在此过程中将建立起一个临时的中断描述符表;

b)        startup_32()函数(包含在arch/i386/kernel/head.S)调用setup_idt()用空的中断处理程序填充IDT,并用IDT表的地址来填充idtr寄存器;

c)        start_kernel()函数完成Linux内核的初始化工作。过程中将调用trap_init()函数和init_IRQ函数以完成IDT初始化。其中trap_init()完成非屏蔽中断和异常描述符的初始化(涉及到的设置函数:set_trap_gate() 、set_intr_gate()、set_system_gate()、set_system_intr_gate()、set_task_gate())。

——————————————————————上述大部分过程可推理至中断———————————————————————


5.      异常处理:

a)        异常发生时,内核(异常处理程序)会向引起异常的进程发送一个信号,这个进程便采取必要的步骤来恢复或中止运行。

b)        Linux利用CPU异常管理硬件资源:

                        i.             “Device not available”异常与cr0的TS标志一起用来把新值装入浮点寄存器;

                      ii.             “Page Fault”异常推迟给进程分配新的页框,直到不能再推迟为止。

c)        “Double fault”异常表示内核有严重的非法错误,该异常处理是通过任务门完成的,将导致:处理器在自己的私有栈上执行doublefault_fn()异常处理程序。

d)        异常处理程序流程:

Handler_name:         pushl $0/*only for some exceptions */         pushl$do_handler_name         jmp error_code/*会从栈中获取do_handler_name的地址*/         /*……         ……*/         jmp ret_from_exception

6.      从异常返回:

a)        异常或中断返回以恢复某个程序的执行为目的,但是在这样做之前必须考虑几个问题:

                        i.             如果内核控制路径的并发执行数量为1,CPU必须切换到用户态;

                      ii.             如果有任何挂起进程的切换请求,内核就必须执行进程调度;否则,把控制权还给当前进程;

                     iii.             如果有信号(已被挂起)发送到当前进程,就必须处理它;

                     iv.             如果调试程序正在跟踪当前进程的执行,就必须在进程切换回到用户态之前恢复单步执行;

                      v.             如果CPU处于Virtual-8086模式,这种情况必须特殊处理。

b)        异常和中断返回的两个入口点:ret_from_intr()、ret_from_exception()。

0 0
原创粉丝点击