Linux内核:中断体系结构

源码

最适合用于研究的0.11版内核(带注释)

操作系统概论:综述

中断的应用

硬件中断响应
系统调用(SystemCall)
信号中断
系统的异常及错误
自定义中断

硬中断与软中断

硬中断:由硬件(如键盘、网卡)等产生,可以直接中断CPU。
软中断:由当前正在运行的进程产生(如I/O请求的发生),如执行到中断指令。

主要源码位置

源码位于kernel目录下的:

中断类型中断前处理、中断后恢复中断执行
硬中断asm.strap.c
软中断system_call.sfork.c、signal.c、exit.c、sys.c

硬中断初始化程序(traps.c)

参考:Linux0.11版本的set_trap_gate宏分析

trap_init函数主要调用了set_trap_gateset_system_gate两个函数来填写陷阱门(trap gate)的描述符。
在这里插入图片描述
其中set_trap_gate的权限较高,而set_system_gate的权限较低,可被所有用户调用。

冷知识:Liuns自己在此处写的注释是:/* int3-5 can be called from all */

这两个函数位于include/asm/system.h下,定义如下:
在这里插入图片描述
可以看到其实这两个函数只是同一个函数_set_gate的带参宏定义,参数不同,仅此而已。
_set_gate的参数解析:

  • 第一个位置的参数n代表此种中断在IDT数组的索引。
  • 第二个位置的参数15即代表确认门类型为15(即01111,trap gate,陷阱门)。
  • 第三个位置的参数(一个是0,一个是3)代表了DPL,此处分别是Ring0和Ring3。
  • 第四个位置的参数addr为回调函数的地址。

_set_gate函数体是一段内联汇编代码,如下,(具体是干什么用的):
在这里插入图片描述

硬中断处理流程(asm.s)

以下以divide_error的处理流程为例。

1. 保存现场

保存现场指:

  1. SS栈堆寄存器、ESP、EFLAGS寄存器、CS、EIP。
  2. 通用寄存器如AX、BX等

在执行divide_error段之前,已自动进行了保存现场的第一步(代码在哪里?),栈的分布情况如下:

栈底
SS
ESP
EFLAGS
CS
EIP

然后执行divide_erroe段:
将中断服务程序的地址入栈

然后顺序执行no_error_code段:
取ESP所指的内容,即中断服务程序的地址,与EAX的内容交换。
此步完成后,EAX中存了中断服务函数(do_divide_error)的地址,而栈顶被替换为EAX的内容
在这里插入图片描述
接下来是10个入栈操作,执行完pushl $0后栈的分布如下:

栈底
SS
ESP
EFLAGS
CS
EIP
EAX
EBX
ECX
EDX
EDI
ESI
EBP
DS
ES
FS
出错码(此种情况为0)

然后是
在这里插入图片描述
取当前ESP值加上十进制的44B,即向栈底移动了11个位置处的内容,此地址处放的正好是EIP,即中断处理前的程序计数器值,将其入栈。

注意lea指令只是计算,而并不改变ESP的值

至此,所有入栈操作完成,保存现场结束,栈的分布如下:

栈底
SS
ESP
EFLAGS
CS
EIP
EAX
EBX
ECX
EDX
EDI
ESI
EBP
DS
ES
FS
出错码(此种情况为0)
执行中断前的程序计数器值EIP

2. 执行中断服务函数

在这里插入图片描述
EAX中放的是中断服务函数的入口地址,此种情况下是do_divide_error,原型在traps.c中:
在这里插入图片描述
其将ESP、错误码作为参数传入后执行。

3. 恢复现场

在这里插入图片描述
堆栈指针下沉8B,即两个位置,跳过 出错码和执行中断前的EIP,因为这两项是供中断服务函数使用的,现在已经没用了。

跳过后,来到指向FS的位置,从FS到EAX依次出栈,还原所有的寄存器。

此步完成后栈的分布为:

栈底
SS
ESP
EFLAGS
CS
EIP

4. 中断返回

在这里插入图片描述
iret指令从栈中依次恢复EIP到SS。
至此结束。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值