进程、系统调用和进程调度( 二 )


想要在中断处理程序中恢复不同的进程只需要将esp指向不同的进程表即可 。
mov esp, []就是设置切换的目标进程 。是指向进程表的指针,所以我们只需在这条语句前面通过进程调度算法,得到调度的目标进程,然后将指向目标进程的进程表即可 。
添加任务步骤总结
一个值得注意的点
中断重入的处理 。之所以允许中断嵌套,是为了在进程调度的时候允许其他的一些需要及时响应的中断比如键盘中断等,而一旦允许了中断嵌套,时钟中断也就有可能嵌套本身,这可能造成时钟中断的无限嵌套,为了解决这个问题,我们才使用全局变量来识别当前是否是重入的时钟中断,如果是则直接返回 。而对于其他类型的中断则没有影响 。
后面仿照minix的中断处理整理代码
总结来说,minx的中断处理和我们前面的实现总体是一致的,只不过minx更加模块化,代码的耦合性更低,并将()部分和中断处理程序后半部分这两个一致的部分合并成一个,让代码更简洁 。
最后,再将这个中断处理格式写成多行宏的形式,拓展到每一个中断通用的格式,并将其中原来的也用函数指针数组来代替,根据中断向量号来调用不同的中断处理程序 。至此,进程调度的框架已经搭好,甚至同时为整个中断系统都搭好了基本框架,这个框架解决了中断重入问题,可以保证中断处理程序部分才能被重入,而且不能被当前中断程序本身嵌套,只能被别的中断嵌套 。
【进程、系统调用和进程调度】整理代码总结
目前为止整个系统运行过程:

进程、系统调用和进程调度

文章插图
系统调用
系统调用是应用程序和操作系统的桥梁,运行在低特权级的应用程序能够通过它来间接地安装操作系统的规范来使用其不能直接使用的指令或者内存区域 。
这章主要就是在实现一个简单的系统调用的同时也搭建好创建系统调用的框架,这样后面自己添加新的系统调用的时候就很方便了 。
实现一个简单的系统调用
ticks全局变量代表发生时钟中断的次数,就是获取当前发生时钟中断的次数 。
我们的目标是实现进程能够随时通过系统调用来获取ticks值,既然是要能够随时,那自然就想到使用中断来实现 。
发生中断的时候,处理程序从何得知调用的是哪个系统调用函数以及其参数呢?首先自然想到可以用堆栈,因为ring0是可以直接读取ring1的堆栈的,也无需切换堆栈 。这是可以的,但是这里暂时无需传入参数,只要传入一个标号来标识调用的是哪个系统调用即可,所有系统调用只占用一个中断向量号,各个系统调用的函数指针组成一个函数指针数组[]类似 。后面一旦要实现有很多参数的复杂系统调用,用寄存器来传递的话就不现实了,还是得用堆栈,这里暂且先这样 。当然,要能够通过int + 中断向量号来触发种中断处理程序也是需要在idt中初始化相应的中断门(描述符)才行类似宏来实现,先save保存现场,然后调用相应的函数(这才是真正的系统调用函数) 。但是这里有个问题就是,原来的eax是没有用来传东西的,所以save里用了eax,这里把它换成esi就可以解决 。这样save就可以直接用了,无需另外再写 。实际的系统调用函数()放在哪里? 由于ticks看上去是和进程相关的东西,所以这里就单独建一个文件proc.c来放它(主要是因为后面ticks在进程调度里有很多应用)实现正确的调用系统调用后,就要实现的实际功能:也就是设置全局变量ticks,并在里更新它,最后在里获取并返回它 。的应用——更精准的延时函数