Lab 4 Background Knowledge
Memory Layout
因為每個 task 的記憶體是獨立分開的,所以需要為每個 task 分配屬於自己的 user stack 及 kernel stack。目前因為沒有 Dynamic Allocator,所以記憶體都是使用靜態宣告。
+------------------+
| Arm Peripherals |
+------------------+ <- 0x40000000
| GPU Peripherals |
+------------------+ <- 0x3f000000
| . |
+------------------+
| User stack[n] |
+------------------+
| . |
| . |
+------------------+
| User stack[0] |
+------------------+
| Kernel stack[n] |
+------------------+
| . |
| . |
+------------------+
| Kernel stack[0] |
+------------------+
| Interrupt stack |
+------------------+
| kernel/user bss |
+------------------+
| kernel/user data |
+------------------+
| kernel/user text |
+------------------+ <- kernel_base (0x80000)
Interrupt stack 會在第一次 IRQ 觸發時,從 kernel stack 切換過去,好處是可以將一些不屬於任意 task 的操作 (e.g. Timer Interrupt) 所使用的記憶體不要去占用到 kernel stack,會比較乾淨一點。
也有另外一種設計是把 Interrupt stack 不獨立出來,放在 kernel stack 上。
Privilege tasks & User tasks
Privilege tasks:
- 只跑在 kernel mode
- 跑一些需要 kernel mode 權限的程式 (e.g. zombie reaper, idle task)
User tasks:
- 大部分時間都跑在 user mode
- 發生 exception 時切換到 kernel mode
- 當進入/離開 kernel 時,需要保存/復原 context
In common:
- 都有 kernel stack
- 在 kernel mode 時會被 context switch
- 跑在相同的 runqueue
Runtime state
圖片來自 Lab 4 Spec
![](runtime-state.png)
在實驗中,將狀態區分成 5 種:
- Task in User Mode (發生 exception 時到狀態 2)
- Task at entry/exit of kernel routine (保存/復原 context)
- Task runs a kernel routine (使用自己的 kernel stack 跑 kernel code)
- Task in interrupt context (interrupt 可能發生在 user mode 或是 kernel mode,interrupt context 不屬於任何 task,使用 interrupt stack)
- Context switch state (Voluntary context switch / Involuntary context switch)
Scheduler 是一個 Process 嗎?
老師上課很常提到一件事:「kernel 是死的,是存在記憶體的一段 code,process 才是活的。」
Scheduler 其實只是一段 kernel 的 code,用來決定下一個 process 該是誰要跑,由此可知 scheduler 自己其實不是一個 process。