第二周学习了进程的启动与转换, 并且对堆栈框架与中断处理有了更深入的了解。
对于操作系统而言,它需要是多线程的,因此对多线程的管理至关重要。
而这就需要设计到中断的处理。比如说,当用户有输入时,系统根据中断的优先级,接受输入。用户的输入属于硬件中断。而当一个除法运算的分母为0时,系统需要处理计算的错误,这是软件中断。
但是中断不仅仅是调用内核中的中断函数就到此为止了。在调用中断之前,系统需要保存几个寄存器中的值,也就是push(保存现场)。当系统处理完中断之后,需要取回那几个寄存器中的值,也就是pop(恢复现场)。通过这个原理,系统可以实现中断上下文的切换。这个方法同样适用于线程之间也是如此进行切换的。
本周的实验部分,实现了线程切换。总体来说,系统根据线程的优先级(随机产生),已每个时间片为间隔,进行线程之间的切换。在具体实现上,使用了内嵌汇编代码push了当前线程的指令指针寄存器(ip)以及栈顶指针寄存器(sp)。代码如下。
asm volatile(
"pushl %%ebp\n\t" /* save ebp */
"movl %%esp,%0\n\t" /* save esp */
"movl %2,%%esp\n\t" /* restore esp */
"movl $1f,%1\n\t" /* save eip */
"pushl %3\n\t"
"ret\n\t" /* restore eip */
"1:\t" /* next process start here */
"popl %%ebp\n\t"
: "=m" (prev->thread.sp),"=m" (prev->thread.ip)
: "m" (next->thread.sp),"m" (next->thread.ip)
);
这段代码实现了切换进程的功能。
ebp压栈,把当前esp指向的内容赋值给prev->thread.sp(保存esp), 把next->thread.sp赋值给esp(恢复esp)
把标志1赋值给prev->thread.ip(保存eip),将next->thread.ip压栈,并且ret。ret将会修改eip指针,next->thread的状态已经恢复完毕,可以运行。
<img src="https://img-blog.csdn.net/20150315100350063?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2FpY2FpOTQ5NA==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" width="500" height="500" alt="" />
linzhe 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000