第七章 实现中断处理 柳暗花明又一村
本文最后更新于:1 年前
第七章 实现中断处理 柳暗花明又一村
写在前面
落笔前已经完成了这一章节的内容,本章难度不大但要编写的代码比较多,中断处理是os的必需内容,所以还是简单介绍下。
正文
我把代码和头文件分别介绍一下:
主体代码
kernel/kernel.S
1 |
|
定义了33个中断处理程序
数组intr_entry_table记录每个程序入口地址
虽然定义了33个中断处理程序,但是从0x14到0x1f这12个中断向量号本实验是不可能产生的。
kernel/interrupt.c
1 |
|
idt_desc_init():填写33个中断处理程序对应的中断门描述符
pic_init() ; 初始化8259A芯片
加载idt:即赋值IDTR
我们写的33个中断处理程序,前20个的中断向量号是异常,由cpu产生
第21个到第32个中断向量号需保留,所以名字赋值成unknown。所以两块8259A芯片产生的15个中断向量号从0x20到0x2f。其中IRQ7为并口1,IRQ15是保留,伪中断经常用这两个号,这两个接口无法通过IMR屏蔽寄存器来屏蔽,所以需要软件单独处理。伪中断是一种硬件中断,比如中断线路上的电气信号异常等。本次实验只打开了IRQ0,所以由8259A芯片产生的中断向量号只可能是0x20,0x27、0x2f。CPU还可能产生0~19号中断向量号(第15号除外)。上述本次实验可能产生中断向量号,都会进入中断处理程序,在中断处理程序调用general_intr_handler,打印自己的中断向量号,0x27、0x2f的伪中断除外。
kernel/init.c
1 |
|
device/timer.c
1 |
|
kernel/main.c
1 |
|
头文件
kernel/init.h
1 |
|
kernel/interrupt.h
1 |
|
intr_handler是用来修饰33个中断处理程序入口地址数组intr_entry_table[IDT_DESC_CNT]的,该数组位于某个数据段,成员均是地址。
void*是空指针类型,表地址。
lib/kernel/io.h
1 |
|
平时写函数都是把函数体写在.c的文件里,函数声明写在.h里,其他文件要调用就include .h的文件即可。但是这次却把这些函数写在了.h里。static作用域只是此文件,也就是只有此文件才可以调用。
对端口的读写或一段连续的内存对端口读写都可以调用汇编指令inb(AT&A)/ins(intel), outsw等。
但是为了内核使用c语言在main函数完成8259A的设置,所以可以使用c函数封装内联汇编形式,这些函数都是static inline,意味着当调用此函数时不再是函数调用,而是就地展开,不再需要传递参数入栈,执行快,但程序体积更庞大。
之所以这样是因为对端口操作属于I/O操作,非常慢,一旦用户程序调用他们,可能会等很长时间,所以在函数调用方面就要尽可能快来追求更短的总时间。
kernel/global.h
1 |
|
device/timer.h
1 |
|
写在后面
不知不觉已经走过了将近一半的路程,回过头看实在艰辛,不过想想自己在这几天收获的东西真是很多。下一章节不准备向下进行了,我想把这半程的过程重新整理一下,并且把代码托管到github上。收拾一下行囊,再出发!
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!