## ## A kernel page table per process ([hard](https://pdos.csail.mit.edu/6.S081/2020/labs/guidance.html))
### 为什么要对进程的页表做四次映射
```c
kvmmapkern(pagetable, UART0, UART0, PGSIZE, PTE_R | PTE_W);
kvmmapkern(pagetable, VIRTIO0, VIRTIO0, PGSIZE, PTE_R | PTE_W);
kvmmapkern(pagetable, CLINT, CLINT, 0x10000, PTE_R | PTE_W);
kvmmapkern(pagetable, PLIC, PLIC, 0x400000, PTE_R | PTE_W);
return pagetable;
```
这四次映射是为了让进程能访问不同的硬件设备,每个映射对应一个不同的设备:
UART0 (Universal Asynchronous Receiver/Transmitter)
kvmmapkern(pagetable, UART0, UART0, PGSIZE, PTE_R | PTE_W);
串口通信设备
用于控制台输入输出
比如 printf 就需要通过 UART 输出
VIRTIO0
kvmmapkern(pagetable, VIRTIO0, VIRTIO0, PGSIZE, PTE_R | PTE_W);
虚拟 I/O 设备接口
用于磁盘操作
比如文件读写需要通过这个接口
CLINT (Core Local Interruptor)
kvmmapkern(pagetable, CLINT, CLINT, 0x10000, PTE_R | PTE_W);
- 处理器本地中断控制器
用于定时器中断
比如进程调度需要用到
PLIC (Platform-Level Interrupt Controller)
kvmmapkern(pagetable, PLIC, PLIC, 0x400000, PTE_R | PTE_W);
平台级中断控制器
处理外部设备中断
比如键盘、磁盘等设备的中断
这些映射是必需的,因为:
1. 每个设备都有其特定的物理地址
2. 内核需要通过这些地址访问设备
3. 没有这些映射,内核就无法与设备通信
就像一个城市需要:
- 港口(UART)用于对外通信
- 仓库(VIRTIO)用于存储
- 警报系统(CLINT)用于定时
- 交通控制(PLIC)用于协调
每个设备都有其特定用途,缺一不可。