麻雀虽小五脏俱全的一个小而全的类unix教学用操作系统,由MIT开发
多核的操作系统,大约6000行还有大约300行的汇编,代码简洁易懂,有很多设计都值得借鉴。
一些特性
- 有进程管理功能
- 有虚拟地址和空间,pagetable
- 文件系统
- 时间片
- 21个syscall
用户程序
sh cat echo grep kill 能够被视为一个真正的操作系统
缺失的功能
- 用户ID
- 登录功能
- 文件保护
- 虚拟内存
- 无法联网
- 只有两个设备驱动
xv6特性
SMP 多线程共享内存
设备
- UART 发送字节流,从一端到另一端
- disk 磁盘驱动器
- 定时器
- PLIC 平台级中断控制器,哪个核心应该被告诉中断
- CLINT 本地中断控制器
内存管理
- pagesize 4096B
- 一个freelist
- 没有可变的内存分配
- 没有“malloc”
- 三级页表 sv39,在pgtbl 巨页中有用到
调度器
基本的循环调度 时间片的大小是固定的 所有的核心共享一个就绪队列,循环的寻找可以执行的进程 不是完全的循环,如果在时间片内结束,会把这个进程放进队列然后换一个来
启动顺序
加载核心代码到固定的地址0x8000_0000,没有bios,bootloader bootblock
锁
- 自旋锁,sleep(),wakeup()
param.h
用户地址空间
函数的参数将会被放在栈中。
xv6的虚拟地址
sv39,三级页表之地
实际上xv6只使用了38位所以最大的是256GB
xv6启动过程和组织
控制权逐步的转移
数据的类型
自旋锁
循环不断的检查,直到能够获取锁为止
test and set,原子的操作。
释放的时候直接修改值就行,可能看起来不是很原子,但是在内存里这被视为一个单独的操作。
不应该长时间被持有,获取锁之后应该尽快释放。可以使用sleep和wakeup进行长时间的获取锁。
一个使用自旋锁的例子 buffer
pushoff popoff
内存管理
kalloc and kfree
将在初始化的时候第一个使用
系统调用
在用户模式下
==kill()==
risc-v架构
寄存器
一共32个寄存器
a0用于存放返回函数返回值
三种模式
- 机器模式(machine mode),是最高权限的模式,但是用的并不多,基本是两种情况,一个是启动和初始化,另一个是定时器中断,程序会很快的转变为对supervisor mode的中断。
- supervisor mode,所有的内核态代码和一些特权指令(只能在S 和M模式下执行的)。
- 用户模式,我们可以说在supervisor 模式下运行的代码都是核心代码,反之亦然
19个寄存器
页表结构
更改satp的时候需要更新flash
只用了38位
在user mode下
在机器模式下
上下文切换
trapfram 和trampoline
调度函数
switch.s
UART.C
16550a芯片与外部设备进行交互
虚拟内存的操作函数
页表结构
一个页表树
标志位只在最后一级页表是最重要的,前两级都只有有效位是有用的,其他都为0.
一些函数
==walk()==
返回页表项的地址。
==mappages()==
==walkaddr()==
把虚拟地址转换成物理地址。
必须是可用的而且是 用户页