目录
1.硬件中断
2. 时钟中断
3. OS本质
4. 软件中断
缺页中断?内存碎片处理?除零野指针错误?
操作系统本质总结
操作系统是对软件硬件资源管理的软件
1.硬件中断
- 中断向量表(IDT)就是操作系统的⼀部分,启动就加载到内存中了,中断向量表本质就是函数指针表
- 由外部设备触发的,中断系统运行流程,叫做硬件中断
- 通过外部硬件中断(外设物理电路链接了cpu的针脚),操作系统就不需要对外设进行任何周期性的检测或者轮询.
- 假设用户按下键盘上的一个键,键盘硬件会发送一个中断信号给CPU。CPU检测到这个信号后,保存当前程序状态,跳到键盘中断服务例程处理按键输入(根据中断号+查表执行处理方法),完成后,CPU恢复之前程序的状态,继续执行。
硬件中断的流程通常包括以下几个步骤:
中断触发:当外部设备或系统内部条件满足中断触发条件时,它会向CPU发送一个中断信号。
中断响应:CPU检测到中断信号后,会暂停当前正在执行的程序,保存当前程序的状态(包括程序计数器、寄存器状态等)。
中断服务例程(Interrupt Handler):CPU根据传入的中断号跳转到预定义的中断服务例程(Interrupt Service Routine,ISR)地址(此地址在操作系统中的中断向量表)执行。此时知道了中断号和中断向量表 ,使用IDT[终端号]就可以执行处理方法
中断处理:中断服务例程执行实际处理中断事件,如读取键盘输入、处理错误恢复、更新定时器处理等。
中断返回:中断服务例程完成后,CPU从中断返回到被暂停的程序继续执行,恢复之前的状态。
2. 时钟中断
问题:
- 问题一: 进程可以在操作系统的指挥下,被调度,被执行,那么操作系统自己被谁指挥,被谁推动执行呢?
- 问题二: 外部设备可以触发硬件中断,但是这个是需要用户或者设备自己触发,有没有自己可以定期触发的设备?
- 计算机中需要严格把控时间,例如单cpu执行多进程需要调度(调度不一定是切换,进程时间片到了才需要切换),要严格按照时间片.
- 时钟源(Clock Source)是提供时间基准信号的设备或机制,老式的时钟源在cpu外部 ,新式的时钟源在CPU内部
- 时钟源以固定周期一直发硬件中断给CPU ,时钟源的IDT[终端号] 的中断服务是进程调度 (类似于硬件中断的中断服务是外设相关操作) ,可以使得OS一直调度进程 . 时钟源每触发一次 正在调度的进程时间片就减少一次,减完了就切换进程 ,这样,操作系统不就在硬件的推动下,自动调度了么!!!
- 时钟源的频率也就是主频 ,也就解释了CPU为什么会有主频?为什么主频越快,CPU越快?
答案一: OS在被时钟源推动执行
答案二:时钟源自己以固定周期触发
3. OS本质
如果是这样,操作系统不就可以躺平了吗?对,操作系统自己不做任何事情,需要什么功能,就向中断向量表里面添加方法即可.
操作系统的本质:就是⼀个死循环!
void main(void) /* 这⾥确实是void,并没错。 */
{ /* 在startup 程序(head.s)中就是这样假设的。 */ .../** 注意!! 对于任何其它的任务,'pause()'将意味着我们必须等待收到⼀个信号才会返 * 回就绪运⾏态,但任务0(task0)是唯⼀的意外情况(参⻅'schedule()'),因为任 * 务0 在任何空闲时间⾥都会被激活(当没有其它任务在运⾏时), * 因此对于任务0'pause()'仅意味着我们返回来查看是否有其它任务可以运⾏,如果没 * 有的话我们就回到这⾥,⼀直循环执⾏'pause()'。 */for (;;)pause();} // end main
4. 软件中断
- 上述外部硬件中断,需要硬件设备触发。
- 有没有可能,因为软件原因,也触发上面的逻辑?有!叫做软中断
- 软中断的目的是执行系统调用
- 为了让操作系统支持进行系统调用,CPU也设计了对应的汇编指令(int 0X80或者 syscall),可以让CPU内部触发中断逻辑 .
- 64位机器是syscall ,32位机器是int 0x80
软中断过程: 先将想要调用的系统调用接口在系统调用表(sys_call_table)的下标index给CPU ,然后执行int 0X80或syscall 触发软中断,让CPU陷入内核阶段 ,OS会执行软中断服务中的sys_call_table[index]方法
问题:
- 用户层怎么把系统调用号给操作系统?寄存器(⽐如EAX)
- 操作系统怎么把返回值给用户?寄存器或者⽤⼾传⼊的缓冲区地址
- 系统调用的过程,其实就是先int 0x80、syscall陷⼊内核,本质就是触发软中断,CPU就会自动执行系统调用的处理方法,而这个方法会根据系统调用号,自动查表,执行对应的方法
- 系统调用号的本质:数组下标!
但是为什么我们在代码中调用系统调用接口用的都是::fork() ::close()之类的 ,没有传过系统调用号 ,更不用说int 0x80、syscall了?
那是因为Linux的glibC标准库,给我们把⼏乎所有的系统调⽤全部封装了。
缺页中断?内存碎片处理?除零野指针错误?
缺页中断?内存碎⽚处理?除零野指针错误?这些问题,全部都会被转换成为CPU内部的软中断, 然后走中断处理例程,完成所有处理。有的是进行申请内存,填充页表,进行映射的。有的是用来 处理内存碎⽚的,有的是⽤来给⽬标进⾏发送信号,杀掉进程等等。
操作系统本质总结
中断是操作系统的“神经系统”,让CPU能高效响应外部事件,同时保证多任务调度的灵活性
- 操作系统就是躺在中断处理例程上的代码块!也就是操作系统广泛利用中断机制来协调硬件与软件的交互
- CPU内部的软中断,⽐如int 0x80或者syscall,我们叫做 陷阱
- CPU内部的软中断,⽐如除零/野指针等,我们叫做 异常。(所以,能理解“缺页异常” 为什么这么叫了吗?)
- 陷阱(进程主动调用系统调用)和异常(CPU执行出错) 都是触发软件异常