完成一个简单的时间片轮转多道程序内核代码
实验目的:
运行并分析一个精简的操作系统内核,理解操作系统是如何工作的
实验过程:
一、
打开终端shell,输入以下命令:
cd LinuxKernel/linux-3.9.4
qemu -kernel arch/x86/boot/bzImage
会弹出一个QEMU终端窗口
打开mymain.c文件,可以看到其中只有如下这一个函数
void__init
my_start_kernel(void) {
inti = 0;
while(1) {
i++;
if(i%100000== 0)
printk(KERN_NOTICE "my_start_kernel here %d \n",i); } }
当mykernel自制操作系统启动后,即qemu命令执行后,系统会首先调用mymain产生一个进程,该进程内while循环条件恒为1所以永远执行输出“my_start_kernel here”+累计循环次数。
并且进行无限循环。
此时由系统时钟中断触发调用myinterrupt产生一个新进程,并输出“my_timer_handler here”,结束后返回mymain产生的进程继续执行,等待下一次系统时钟中断触发调用myinterrupt产生一个新进程,myinterrupt产生的新进程和上一次的属于不同的进程,而mymain由于循环没有终止的时候,所以永远是原来的那个进程。
通过观察可以发现,当执行myinterrupt后返回mymain时,终端输出的累计循环次数是连续的,并没有中断或重置,说明CPU和内核代码共同实现了保存现场和恢复现场的功能,会将一些重要的寄存器,比如eip、ebp、esp等保存下来,等待切换回来的时候继续执行。
二、修改内核
替换位于home/shiyanlou/LinuxKernel/linux-3.9.4/mykernel/中的mymain.c;myinterrupt.c; 同时也把mypcb.h也放在这里。
接下来在shell中将当前工作目录退回到home/shiyanlou/LinuxKernel/linux-3.9.4/
然后执行make,重新编译内核。
然后再次输入:qemu -kernel arch/x86/boot/bzImage 启动内核。
得到结果
这里 my_timer_handler 函数会被内核周期性的调用,每调用1000次,就去将全局变量my_need_sched的值修改为1,通知正在执行的进程执行调度程序my_schedule。
在my_schedule函数中,完成进程的切换。
进程的切换分两种情况,一种情况是下一个进程没有被调度过,另外一种情况是下一个进程被调度过,可以通过下一个进程的state知道其状态。
进程切换依然是通过内联汇编代码实现,无非是保存旧进程的eip和堆栈,将新进程的eip和堆栈的值存入对应的寄存器中。
三、实验总结
通过本讲的学习和实验,我知道操作系统的两个核心功能是进程调度和中断机制
进程调度是指系统中处于就绪状态的进程对处理机的竞争是由进程调度程序来协调的。调度是依照确定的策略将一批进程排序,从就绪队列中移出一个进程并给它提供处理机的使用权。
中断机制是指在操作系统中,linux内核要对连接到计算机上的所有硬件设备进行管理,这是它份内的工作。而想要管理这些设备,首先要能和它们互通音信才行。