Lab 4: Preemptive Multitasking
简介
本次实验我们将要实现在多并发进程的情况下实现抢占式多任务,在PartA中,将为JOS提供多处理器支持,实现循环调度,并添加基本的进程管理系统调用(创建和销毁环境以及分配/映射内存的调用)。在PartB中,将实现一个类Unix的fork(),它允许用户进程创建子进程。最后,在PartC中,将提供对进程间通信(IPC)的支持,从而允许不同的用户进程进行通信和同步。 还将添加对硬件时钟中断和抢占的支持。
预备工作:首先按课程提示提交lab3代码然后检出lab4代码并合并,lab4包含了一组新的源文件:
kern / cpu.h, 支持多处理器的内核私有定义
kern / mpconfig.c 读取多处理器配置的代码
kern / lapic.c 在每个处理器中驱动本地APIC单元的内核代码
kern / mpentry.S 非引导CPU的汇编语言入口代码
kern / spinlock.h 自旋锁(包括大内核锁)的内核私有定义
kern / spinlock.c 实现自旋锁的内核代码
kern / sched.c 将要实现的调度程序的代码框架
实验要求:本实验分为三部分,每部分限时一周,你应当完成实验中要求的所有练习并解决至少一个挑战问题,并为实现的挑战问题写一个简短的描述说明。
Part A: Multiprocessor Support and Cooperative Multitasking
在本实验的第一部分,我们将首先扩展JOS以使其在多处理器系统上运行,然后实现一些新的JOS内核系统调用,以允许用户进程创建其他新进程。 还将实现协作循环调度,在当前进程自愿放弃CPU(或退出)时,允许内核切换进程。 在PartC中,还将实现抢占式调度,该调度使内核可以在经过一定时间后从进程手中强制重新获得对CPU的控制。
Multiprocessor Support
我们将使JOS支持“对称多处理”(SMP),一种多处理器模型,其中所有CPU都具有对系统资源(例如内存和I / O总线)的同等访问权限。 尽管所有CPU在SMP中在功能上都是相同的,但是在引导过程中,它们可以分为两种类型:引导处理器(BSP)负责初始化系统和引导操作系统; 仅在操作系统启动并运行后,BSP才会激活应用程序处理器(AP)。 哪个处理器是BSP由硬件和BIOS决定。 到目前为止,您所有现有的JOS代码都已在BSP上运行。
在SMP系统中,每个CPU都有一个随附的本地APIC(LAPIC)单元。 LAPIC单元负责在整个系统中传递中断。 LAPIC还为其连接的CPU提供唯一的标识符。 在本实验中,我们利用LAPIC单元的以下基本功能(在kern / lapic.c中):
1.读取LAPIC标识符(APIC ID)以了解我们的代码当前在哪个CPU上运行(请参阅cpunum())。
2.从BSP发送 STARTUP 处理器间中断(IPI)到AP以唤醒其他CPU(请参阅lapic_startap())。
3.在PartC中,我们对LAPIC的内置计时器进行编程,以触发时钟中断以支持抢占式多任务(请参阅apic_init())。
处理器使用内存映射的I / O(MMIO)访问其LAPIC。 在MMIO中,一部分物理内存被硬连线到某些I / O设备的寄存器,因此通常用于访问内存的相同加载/存储指令可用于访问设备寄存器。 您在物理地址0xA0000上有一个I/O Hole(我们使用它来写入VGA显示缓冲区)。 LAPIC的Hole开始于物理地址0xFE000000(4GB下的32MB),但是这地址太高,我们无法访问。 不过JOS虚拟内存映射在MMIOBASE处预留了4MB的空间,因此我们需要建立映射关系。
练习1:
实现kern/pmap.c的mmio_map_region函数,阅读kern/lapic.c的lapic_init函数来看看这个函数怎么被使用的,另外在测试mmio_map_region之前,得先完成下一个练习。
按注释实现mmio_map_region()就行了:
Application Processor Bootstrap
在启动AP之前,BSP首先收集有关多处理器系统的信息,例如CPU的总数,它们的APIC ID和LAPIC单元的MMIO地址。 kern / mpconfig.c中的mp_init()函数通过读取驻留在BIOS内存区域中的MP配置表来检索此信息。
kern / init.c中的boot_ap