本仓库仅供参考,切勿抄袭!详细的实验文档请参考:详细文档
熟悉现有Linux内核的编译过程和启动过程, 并在自行编译内核的基础上构建简单应用并启动。同时,利用精简的Busybox工具集构建简单的OS, 熟悉现代操作系统的构建过程。 此外,熟悉编译环境、相关工具集,并实现内核远程调试。具体内容如下:
- 搭建OS内核开发环境包括:代码编辑环境、编译环境、运行环境、调试环境等。
- 下载并编译i386(32位)内核,并利用qemu启动内核。
- 熟悉制作initramfs的方法。
- 编写简单应用程序随内核启动运行。
- 编译i386版本的Busybox,随内核启动,构建简单的OS。
- 开启远程调试功能,进行调试跟踪代码运行。
学习到x86汇编、计算机的启动过程、IA-32处理器架构和字符显存原理。根据所学的知识,能自己编写程序,然后让计算机在启动后加载运行,以此增进对计算机启动过程的理解,为后面编写操作系统加载程序奠定基础。同时,学习如何使用gdb来调试程序的基本方法。
- 学习 IA-32 处理器
- 学习汇编基础
- 熟悉计算机开机启动过程
- 编写 MBR
学习到如何从16位的实模式跳转到32位的保护模式,然后在平坦模式下运行32位程序。同时,学习如何使用I/O端口和硬件交互,为后面保护模式编程打下基础。
- MBR 与 bootloader
- LBA方式读写硬盘
- 保护模式
- 加载 bootloader
- 进入保护模式
了解一份C代码是如何通过预编译、编译、汇编和链接生成最终的可执行文件。接着,为了更加有条理地管理我们操作系统的代码,提出了一种C/C++项目管理方案。在做了上面的准备工作后,开始介绍C和汇编混合编程方法,即如何在C代码中调用汇编代码编写的函数和如何在汇编代码中调用使用C编写的函数。介绍完混合编程后,我们来到了本章的主体内容——中断。介绍了保护模式下的中断处理机制和可编程中断部件8259A芯片。最后,通过编写实时钟中断处理函数来将本章的所有内容串联起来。
通过本章的学习,掌握使用C语言来编写内核的方法,理解保护模式的中断处理机制和处理时钟中断,为后面的二级分页机制和多线程/进程打下基础。
- 从代码到可执行文件
- 使用Makefile编译C/C++项目
- C/C++和汇编混合编程
- 保护模式下的中断
- 8259A芯片
学习到C语言的可变参数机制的实现方法。在此基础上,揭开可变参数背后的原理,进而实现可变参数机制。实现了可变参数机制后,实现一个较为简单的printf函数。此后,我们可以同时使用printf和gdb来帮助我们debug。
本次实验另外一个重点是内核线程的实现,我们首先会定义线程控制块的数据结构——PCB。然后,我们会创建PCB,在PCB中放入线程执行所需的参数。最后,我们会实现基于时钟中断的时间片轮转(RR)调度算法。在这一部分中,我们需要重点理解asm_switch_thread是如何实现线程切换的,体会操作系统实现并发执行的原理。
- printf 的实现
- 内核线程
- 线程的描述
- PCB 的分配
- 线程的创建
- 线程的调度
- 第一个线程
使用硬件支持的原子指令来实现自旋锁SpinLock,自旋锁将成为实现线程互斥的有力工具。接着,使用SpinLock来实现信号量,最后使用SpinLock和信号量来给出两个实现线程互斥的解决方案。
- 自旋锁方案
- 信号量方案
学习如何使用位图和地址池来管理资源。然后,我们将实现在物理地址空间下的内存管理。接着,我们将会学习并开启二级分页机制。在开启分页机制后,我们将实现在虚拟地址空间下的内存管理。
本次实验最精彩的地方在于分页机制。基于分页机制,我们可以将连续的虚拟地址空间映射到不连续的物理地址空间。同时,对于同一个虚拟地址,在不同的页目录表和页表下,我们会得到不同的物理地址。这为实现虚拟地址空间的隔离奠定了基础。但是,本实验最令人困惑的地方也在于分页机制。开启了分页机制后,程序中使用的地址是虚拟地址。我们需要结合页目录表和页表才能确定虚拟地址对应的物理地址。而我们常常会忘记这一点,导致了我们不知道某些虚拟地址表示的具体含义。
- 内存的探查
- 位图
- 地址池
- 物理页内存管理
- 二级分页机制
- 虚拟页内存管理
简单讨论保护模式下的特权级的相关内容。特权级保护是保护模式的特点之一,通过特权级保护,我们区分了内核态和用户态,从而限制用户态的代码对特权指令的使用或对资源的访问等。但是,用户态的代码有时不得不使用一些特权指令,如输入输出等。因此,我们介绍了系统调用的概念和如何通过中断来实现系统调用。通过系统调用,我们可以实现从用户态到内核态转移,然后在内核态下执行特权指令等,执行完成后返回到用户态。在实现了系统调用后,我们通过三步来创建了进程。这里,我们需要重点理解我们是如何通过分页机制来实现进程之间的虚拟地址空间的隔离。最后,我们介绍了fork/wait/exit的一种简洁的实现思路。
- 特权级
- 系统调用的实现
- 进程的实现
- 进程的调度
- 第一个进程
- 加入更大系统调用
- fork
- exit
- wait
之前已经实现了以页为粒度的动态内存分配和释放。但是,我们在程序中使用的往往是以字节为粒度的动态内存管理机制,即我们可以分配和释放任意字节长度的内存。
本项目需要实现系统调用malloc和free。malloc用于分配任意字节的内存,free用于释放任意字节的内存。在实现了malloc和free后,需要自行提供测例来测试malloc和free。根据测试方法和输出结果来解释自己程序的正确性。