System Call
前面在 exception 的實驗有實作簡單的 system call,現在要擴充 system call 的功能。
Trapframe
還記得前面的 kernel_entry
會將目前的 context push 進 kernel stack:
|
|
我們把這段記憶體叫做 Trapframe。
| . |
|------------------------| --+
| task 1 saved registers | |-- trapframe
|------------------------| --+
| . |
| . |
+------------------------+ <- task 1 kenrel stack
Trapframe 是 user space 與 kernel space 溝通的橋樑:
- user 可以設定參數與 system call number,當進入 kernel 後就可以透過 trapframe 存取
- kernel 可以修改 trapframe,當作 system call 的回傳值
exception.h
首先先定義一下 trapframe 的 structure,這部分跟你 push 進 stack 的順序有關,我是這樣定的:
|
|
User library API
將 system call 為不同 architechture / os 包裝一層 API。參考 ARM 的 calling convention,我將 system call number 放在 x8
sys.h
|
|
sys.S
|
|
Synchronous Exception Handler
如果是 svc
處發的 synchronous exception,就當作是 system call。將 system call number 從 trapframe 取出,並呼叫 sys_call_router
。
exception.c
|
|
Interface for System Call
根據 system call number 分配不同的 handler。
exception.c
|
|
System call handler
將 return value 放在 x0
get_taskid
拿到目前的 task id。
exception.c
|
|
uart_read
從 user space 傳進一個 char 指標與希望讀的大小。
exception.c
|
|
uart_write
將 user space 傳進來的 char 陣列寫入 size 個 char。
exception.c
|
|
exec
將傳進來的 function pointer 當作 do_exec
的參數。
exception.c
|
|
fork
將目前 task 的狀態複製一份給 child,parent 回傳 child task id,child 回傳 0。
exception.c
|
|
offset 示意圖:
| . |
|----------------------| <- char* trapframe (low)
| task saved registers |
|----------------------|
| . |
| . |
+----------------------+ <- char* parent_kstack (high)
exit
exit 時將 task 狀態改成 zombie,並 reschedule。
exception.c
|
|
schedule.c
|
|
Zombie reaper
用來檢查如果有 task 是 zombie state,就將他的記憶體釋放,並將狀態改成 EXIT
最好不要讓 EXIT process 自己釋放記憶體
實作方式:
- A privilege_task that always check if there are zombie tasks. (Easier)
- Each task has its parent task, the parent should use wait function to check and reap zombie child task.
我是使用簡單版的方式
schedule.c
|
|