理解操作系统是如何工作的之进程调度

曹朋辉
原创作品转载请注明出处
《Linux内核分析》MOOC课程

首先用老师提供的代码运行一下,可以看到她跑起来的最终样子。

理解操作系统是如何工作的之进程调度_第1张图片
实验结果

确实没啥好看的,还是去分析代码吧。
刚看到作业时以为是要自己写代码,操作系统还没系统学过的我,一下懵了,上完课才知道老师已经提供了代码理解就好。
实验中我们用到了三个文件

mymain.c 此文件中包含操作系统的入口函数,最终我们通过此函数拉起一个进程,完成操作系统的初始化
myinterrupt.c 此文件中包含终端处理函数和进程调度函数
mypcb.h 定义了进程调度用到的数据结构

本次实验的重点分别为如下几个过程
一 . 操作系统的初始化, my_start_kernel函数会创建多个进程并拉起第一个进程,实现思路为通过嵌入式汇编修改eip,与esp

asm volatile(

"movl %1,%%esp\n\t" /* set task[pid].thread.sp to esp */

"pushl %1\n\t" /* push ebp */

"pushl %0\n\t" /* push task[pid].thread.ip */

"ret\n\t" /* pop task[pid].thread.ip to eip */

"popl %%ebp\n\t"

:

: "c" (task[pid].thread.ip),"d" (task[pid].thread.sp) /* input c or d mean %ecx/%edx*/

);

}

二、进程的切换
进程切换的主要问题就是如何保存和恢复函数栈帧及改变eip的值。
下面既是实现进程切换的主要代码

/* switch to next process */

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)

);

"pushl %%ebp\n\t" /* save ebp */执行后esp中就就存储了ebp的值,因为我们只存储了esp的值因此这是了解如何恢复ebp的关键。

"movl $1f,%1\n\t" /* save eip */ 保存"1:\t" /* next process start here */代码的地址到当前进程的thread.ip, 下次切换回来时从此处接着继续执行。

"pushl %3\n\t" 

"ret\n\t" /* restore eip */

将eip指向下一进程的代码继续执行。

以上代码为一个进程切换到一个已经运行的程序,如果是切换到一个新进程,代码会有些许不同,主要是新进程没有之前保存的栈帧信息,大体思路还是一样的。

总结

这次实验懂得了嵌入式汇编的基本用法,了解进程是如何切换的。

你可能感兴趣的:(理解操作系统是如何工作的之进程调度)