操作系统开发系列—12.f.在内核中添加中断处理 ●
因为CPU只有一个,同一时刻要么是客户进程在运行,要么是操作系统在运行,如果实现进程,需要一种控制权转换机制,这种机制便是中断。
要做的工作有两项:设置8259A和建立IDT。
/*======================================================================*
init_8259A
*======================================================================*/
PUBLIC void init_8259A()
{
/* Master 8259, ICW1. */
out_byte(INT_M_CTL, 0x11);
/* Slave 8259, ICW1. */
out_byte(INT_S_CTL, 0x11);
/* Master 8259, ICW2. 设置 '主8259' 的中断入口地址为 0x20. */
out_byte(INT_M_CTLMASK, INT_VECTOR_IRQ0);
/* Slave 8259, ICW2. 设置 '从8259' 的中断入口地址为 0x28 */
out_byte(INT_S_CTLMASK, INT_VECTOR_IRQ8);
/* Master 8259, ICW3. IR2 对应 '从8259'. */
out_byte(INT_M_CTLMASK, 0x4);
/* Slave 8259, ICW3. 对应 '主8259' 的 IR2. */
out_byte(INT_S_CTLMASK, 0x2);
/* Master 8259, ICW4. */
out_byte(INT_M_CTLMASK, 0x1);
/* Slave 8259, ICW4. */
out_byte(INT_S_CTLMASK, 0x1);
/* Master 8259, OCW1. */
out_byte(INT_M_CTLMASK, 0xFF);
/* Slave 8259, OCW1. */
out_byte(INT_S_CTLMASK, 0xFF);
}
out_byte的函数体位于kliba.asm中
global out_byte
global in_byte ; ========================================================================
; void out_byte(u16 port, u8 value);
; ========================================================================
out_byte:
mov edx, [esp + 4] ; port
mov al, [esp + 4 + 4] ; value
out dx, al
nop ; 一点延迟
nop
ret ; ========================================================================
; u8 in_byte(u16 port);
; ========================================================================
in_byte:
mov edx, [esp + 4] ; port
xor eax, eax
in al, dx
nop ; 一点延迟
nop
ret
现在,该是把这些中断和异常的处理程序统统添加上的时候了。
global divide_error
global single_step_exception
global nmi
global breakpoint_exception
global overflow
global bounds_check
... lidt [idt_ptr] ...
; 中断和异常 -- 异常
divide_error:
push 0xFFFFFFFF ; no err code
push 0 ; vector_no = 0
jmp exception
single_step_exception:
push 0xFFFFFFFF ; no err code
push 1 ; vector_no = 1
jmp exception
nmi:
push 0xFFFFFFFF ; no err code
push 2 ; vector_no = 2
jmp exception
breakpoint_exception:
push 0xFFFFFFFF ; no err code
push 3 ; vector_no = 3
jmp exception
overflow:
push 0xFFFFFFFF ; no err code
push 4 ; vector_no = 4
jmp exception
...
exception:
call exception_handler
add esp, 4*2 ; 让栈顶指向 EIP,堆栈中从顶向下依次是:EIP、CS、EFLAGS
hlt
异常发生时堆栈的变化情况是,中断或异常发生时eflags、cs、eip已经被压栈,如果有错误码的话,错误码也已经被压栈。
所以我们对异常处理的总体思想是,如果有错误码,则直接把向量号压栈,然后执行一个函数exception_handler;如果没有错误码,则先在栈中压入一个0xFFFFFFFF,再把向量号压栈并随后执行exception_handler。
函数exception_hanlder()的原型是这样的:
void exception_handler(int vec_no,int err_code,int eip,int cs,int eflags);
由于C调用约定是调用者恢复堆栈,所以不用担心exception_handler会破坏堆栈中的eip、cs以及eflags。
现在我们已经有了异常处理函数,该是设置IDT的时候了。设置IDT的代码放进函数init_prot()中,它也位于protect.c中。protect.c通篇几乎只调用一个函数,就是init_idt_desc(),它用来初始化一个门描述符。其中用到的函数指针类型是这样定义的:
typedef void (*int_handler) ();
在init_prot()中,所有描述符都被初始化成中断门。DA_386IGate表示中断门。
Intel为我们准备了一个指令叫做ud2,能够产生一个#UD异常。
编译:
make image
运行结果如下:


【源码】
操作系统开发系列—12.f.在内核中添加中断处理 ●的更多相关文章
- 操作系统开发系列—12.g.在内核中设置键盘中断
8259A虽然已经设置完成,但是我们还没有真正开始使用它呢. 所有的中断都会触发一个函数spurious_irq(),这个函数的定义如下: PUBLIC void spurious_irq(int i ...
- 操作系统开发系列—12.d.扩充内核 ●
现在把esp.GDT等内容放进内核中,我们现在可以用C语言了,只要能用C,我们就避免用汇编. 下面看切换堆栈和GDT的关键代码: ; 导入函数 extern cstart ; 导入全局变量 exter ...
- 操作系统开发系列—12.c.从Loader加载ELF内核,顺便解释下函数调用过程 ●
实际上,我们要做的工作是根据内核的Program header table的信息进行类似下面这个C语言语句的内存复制: memcpy(p_vaddr, BaseOfLoaderPhyAddr+p_of ...
- 操作系统开发系列—12.a.从Loader到内核 ●
Loader要做两项工作,我们先来做第一项,把内核加载到内存: 1.加载内核到内存. 2.跳入保护模式. 首先编译无内核时: nasm boot.asm -o boot.bin nasm loader ...
- 操作系统开发系列—12.e.Makefile
先来看一个简单的Makefile,我们把它放在目录/boot下,可以用来编译boot.bin和loader.bin. # Makefile for boot # Programs, flags, et ...
- 操作系统开发系列—12.b.从Loader跳入保护模式
现在,内核已经被我们加载进内存了,该是跳入保护模式的时候了. 首先是GDT以及对应的选择子,我们只定义三个描述符,分别是一个0~4GB的可执行段.一个0~4GB的可读写段和一个指向显存开始地址的段: ...
- Windows下USB磁盘开发系列二:枚举系统中所有USB设备
上篇 <Windows下USB磁盘开发系列一:枚举系统中U盘的盘符>介绍了很简单的获取系统U盘盘符的办法,现在介绍下如何枚举系统中所有USB设备(不光是U盘). 主要调用的API如下: 1 ...
- Windows下USB磁盘开发系列三:枚举系统中U盘、并获取其设备信息
前面我们介绍了枚举系统中的U盘盘符(见<Windows下USB磁盘开发系列一:枚举系统中U盘的盘符>).以及获取USB设备的信息(见<Windows下USB磁盘开发系列二:枚举系统中 ...
- 向linux内核中添加外部中断驱动模块
本文主要介绍外部中断驱动模块的编写,包括:1.linux模块的框架及混杂设备的注册.卸载.操作函数集.2.中断的申请及释放.3.等待队列的使用.4.工作队列的使用.5.定时器的使用.6.向linux内 ...
随机推荐
- JAVA 设计模式 命令模式
用途 命令模式 (Command) 将一个请求封装为一个对象,从而使你可以用不同的请求对客户进行参数化:对请求排队或请求日志,以及支持可撤销的操作. 命令模式是一种行为型模式. 结构
- JAVA 设计模式 装饰者模式
用途 装饰者模式 (Decorator) 动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator 模式相比生成子类更为灵活. 装饰者模式是一种结构式模式. 结构
- ES6笔记(7)-- Promise异步编程
系列文章 -- ES6笔记系列 很久很久以前,在做Node.js聊天室,使用MongoDB数据服务的时候就遇到了多重回调嵌套导致代码混乱的问题. JS异步编程有利有弊,Promise的出现,改善了这一 ...
- 拓扑排序 --- hdu 4948 : Kingdom
Kingdom Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Sub ...
- 【转】同一台Windows机器中启动多个Memcached服务
上一篇介绍了Memcached的安装,但是如果手头上只有一台机器,又想做多节点测试咋办? 这就需要在一台机器上启动多个Memcached服务了. 假设Memcached在如下目录:C:\memcach ...
- Gson操作json
github:https://github.com/google/gson API:http://google.github.io/gson/apidocs/ 示例对象 package present ...
- 会员管理系统的设计和开发(2)-- RDLC报表的设计及动态加载
在上篇<会员管理系统的设计和开发(1)>介绍了关于会员系统的一些总体设计思路和要点,经过一段时间开发,软件终于完成并发布.在这期间,碰到了不少技术难点,并积累了不少开发心得和经验,本篇继续 ...
- C# AD(Active Directory)域信息同步,组织单位、用户等信息查询
示例准备 打开上一篇文章配置好的AD域控制器 开始菜单-->管理工具-->Active Directory 用户和计算机 新建组织单位和用户 新建层次关系如下: 知识了解 我们要用C# ...
- 【CTO讲堂】以API为核心的移动应用云大发展时代
摘要:CTO线上讲堂5月20日正式登场,CTO俱乐部首期邀请到APICloud联合创始人兼CTO邹达与C粉之家微信群友一起聊聊如何快速玩转App开发,分享技术人的职场成长. 为了帮助IT从业者职业之路 ...
- 火狐浏览器+Firebug+FirePath测试Xpath
前言 抓取网页数据时使用HtmlAgilityPack分析,需要通过xpath定位页面元素.如果有个xpath的生成和验证工具就事半功倍了,火狐浏览器插件FirePath配合Firebug就能完美实现 ...