用mykernel 2.0虚拟一个x86-64的CPU硬件平台
一个操作系统那么复杂,它本质上是怎么工作的呢?接下来要做一个有趣的实验。
“天下大事必作于细,天下难事必作于易”。首先搭建一个虚拟的平台,虚拟一个x86-64的CPU,然后使用Linux内核源代码把虚拟CPU初始化配置好时钟中断和程序入口,就可以开始编写自己的操作系统内核了。
为了便于理解实验内容,这里简要介绍中断的基本概念。中断最初用于避免CPU轮询I/O设备,就绪状态发生时让I/O设备主动通过中断信号通知CPU,大大提高了CPU在输入输出上的工作效率,这就是硬件中断(外部中断)。后来随着中断适用范围扩大,比如解决机器运行过程出现的异常情况以及系统调用的实现等,这就产生了软件中断(内部中断),也称为异常,软件中断又分为故障(fault)和陷阱(trap)。
简而言之,在没有中断机制之前,计算机只能一个程序一个程序地执行,也就是批处理,而无法多个程序并发工作。有了中断机制,CPU帮我们做了一件事情,就是当一个中断信号发生时,CPU把当前正在执行的进程X的CS:RIP寄存器和RSP寄存器等都压栈到了一个叫内核堆栈的地方,然后把CS:RIP指向一个中断处理程序的入口,做保存现场的工作,然后去执行其他进程比如Y,等重新回来时再恢复现场,即恢复CS:RIP寄存器和RSP寄存器等到CPU上继续执行原进程X。显然中断机制在计算机系统中发挥着关键作用。
需要说明的是基于mykernel虚拟一个x86-64的CPU硬件平台已经把保存现场和恢复现场的复杂工作已经帮我们完成了,而且为了简化起见mykernel只提供了一个周期性发生的时钟中断。虚拟的CPU硬件平台中模拟了时钟中断,每隔一段时间,发生一次时钟中断,这样我们就有基础写一个时间片轮转调度的操作系统内核,这也是后面的实验目标。下面来具体看看如何基于mykernel虚拟一个x86-64的CPU。先来看如何把这个虚拟的x86-64 CPU实验平台mykernel搭建起来。
wget https://raw.github.com/mengning/mykernel/master/mykernel-2.0_for_linux-5.3.34.patch
sudo apt install axel
axel -n 20 https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.4.34.tar.xz
xz -d linux-5.4.34.tar.xz
tar -xvf linux-5.4.34.tar
cd linux-5.4.34
patch -p1 < ../mykernel-2.0_for_linux-5.3.34.patch
sudo apt install build-essential gcc-multilib
sudo apt install qemu # install QEMU
sudo apt install libncurses5-dev bison flex libssl-dev libelf-dev
make defconfig # Default configuration is based on 'x86_64_defconfig'
make -j$(nproc)
qemu-system-x86_64 -kernel arch/x86/boot/bzImage
搭建起来后的内核启动效果如图所示,从QEMU窗口中您可以看到my_start_kernel在执行,同时my_timer_handler时钟中断处理程序周期性执行。
在Linux-5.3.34内核源代码根目录下进入mykernel目录,可以看到QEMU窗口输出的内容的代码mymain.c和myinterrupt.c ,当前有一个虚拟的CPU执行C代码的上下文环境,可以看到mymain.c中的代码在不停地执行。同时有一个中断处理程序的上下文环境,周期性地产生的时钟中断信号,能够触发myinterrupt.c中的代码。这样就通过Linux内核代码模拟了一个具有时钟中断和C代码执行环境的硬件平台。您只要在mymain.c的基础上继续写进程描述PCB和