一、操作系统工作的基础:
1)存储程序计算机:现代计算机大多基于冯诺依曼体系结构,即存储程序计算机。所谓存储程序计算机,是指将程序存储到计算机中,在将程序加载到内存后,CPU通过取指、译码、执行指令对数据进行处理。
2)函数调用堆栈机制:在没有发生中断和进程切换时,所有的程序的执行都遵循函数调用堆栈机制。所谓i函数调用堆栈机制,是指程序执行中遇到函数调用时,会进行一系列的堆栈操作并改变eip,执行被调函数。
3)中断机制:指系统调用,时钟中断或IO中断¹。中断引起的是一个内核控制路径--所有的操作仍然是在当前进程的地址空间中进行,只不过操作堆栈由用户堆栈切换到了内核堆栈,程序的执行由用户程序切换到了内核程序。程序指令的执行由内核控制,即内核控制路径。为了使内核对中断有较短的响应时间,中断分为上半部和下半部。下半部为一些可以被延后执行的操作,由内核线程完成。
4)内核在运行时可抽象为内核线程和中断处理过程。内核线程为特殊的进程,始终运行在内核态。按照优先级分为软中断、tasklet和工作队列。
5)进程切换:用户程序无法在用户态执行schedule()进行进程切换,该函数只在时钟中断(RR)、I/O中断以及系统调用的exit()中执行。
二、在操作系统工作的基础之上,简述操作系统(内核)是如何工作:
程序在经过编译链接后形成可执行程序。在加载到内存时,系统根据可执行程序初始化进程的地址空间。CPU根据ebp/eip寻址进程地址空间中cs段的代码,取指,译码并依次执行,进行数据处理。
在遇到函数调用时,首先会将参数压栈,接着执行call指令—压栈cs:eip并跳转到被调函数的cs段,然后,构造被调函数的堆栈,之后,同样的取指,译码并依次执行,进行数据处理。在被调函数的结尾,会恢复调用函数的堆栈,然后执行ret指令—cs:eip出栈,继续执行被调函数cs段的指令。详细分析见实验一http://www.cnblogs.com/wenxuanguan/archive/2013/05/16/3082686.html。
当发生中断时,cpu会²将当前进程的eip和esp压栈,将esp指向内核堆栈,将eip指向内核中的中断处理总入口处。在函数中,首先会执行SAVE_ALL保存当前状态,接着调用中断处理例程执行,执行restore_all恢复状态。最后CPU执行iret,返回用户态,恢复系统调用前进程的堆栈和cpu的eip,继续执行当前进程的指令。
在中断处理例程之后会判断是否要进行进程切换。 由于进程切换发生在当前进程的地址空间的内核部分,所以要在切换进程前完成保存CPU的状态和堆栈切换的准备工作;进程切换后,恢复切换进程的内核堆栈并恢复CPU的状态。
1.具体的,每个能够发出中断请求的硬件设备控制器都有一条RQ输出线,所有的IRQ线都与一个中断控制器的输入引脚相连;中断控制器与CPU的INTR引脚相连。
中断控制器会监视IRQ线,如果一个引发信号出现在IRQ线上,首先把此信号转换成对应的中断向量(中断控制器对输入的IRQ线从0开始顺序编号IRQ0 ,IRQ1,… 。Intel给中断控制器分配的中断向量号从32开始,上述IRQ线对应的中断向量依次是32+0、32+1、…);接着把这个向量存放在中断控制器的一个I/O端口,从而允许CPU通过数据总线读这个向量;然后,把引发信号发送到处理器的INTR引脚,即产生一个中断;最后,等待,直到CPU应答这个信号;收到应答后,清INTR引脚。设备,设备控制器,中断控制器及CPU的对中断请求信号的连接如下图所示:
2.确切的说,CPU是根据中断向量号,利用IDT找到相应的中断或异常处理程序的入口地址(其中,128号向量实现系统调用),之后执行压栈和栈切换以及调用中断处理函数。