system call 會涉及到 context switch, 所以需要先理解 context switch (可不是教科書說的理論那種理解, 而是能寫出 context switch code 的那種理解) 才能看懂這裡提到的程式碼。
麻煩一
在使用 svc 來實作 system call, 還是要保存 context, 也就是 context switch 要做的事情, 都要再做一次, 怎麼讓他們共用這段程式碼呢?
麻煩二
如何將 system call 的結果傳回給 proc_a (proc_a 是發動這個 system call 的 process)
麻煩三
如何從 proc_a 傳參數到 system call 裡頭呢?
這個範例程式很醜, 架構也不美, 但它可是我從無到有實實在在完成的, 對我來說, 意義非凡。
本來打算使用 Orange's 一個作業系統的實現 上的實作方式, 我也想好怎麼開始了, 不過 ...
先來看看 Orange's 一個作業系統的實現是怎麼
程式碼請參閱 simple_os
asm_syscall.S
.global get_ticks get_ticks: mov $_NR_GET_TICKS, %eax int $INT_VECTOR_SYS_CALL ret .global write write: mov $_NR_WRITE, %eax mov 4(%esp), %ebx mov 8(%esp), %ecx int $INT_VECTOR_SYS_CALL ret .global sys_call sys_call: call save sti push %esi # why push %esi ?? pushl ready_process push %edx push %ecx push %ebx call *sys_call_table(, %eax, 4) add $16, %esp pop %esi # why pop %esi ?? mov %eax, P_EAX_OFFSET(%esi) # return value save to eax offset in process structure cli ret
填入 system call 編號到 %eax, 觸發 0x90 中斷 (int 0x90), 這時候會跑到 sys_call (透過 IDT 設定的結果), 再根據 sys_call_table, 編號去執行 sys_call_table 裡頭的 function (ref: syscall.c), 再把傳回值寫到 process stack frame 的 %eax 欄位, system call 結束後, process 的 %eax 自然就得到該 system call 的傳回值。
如何把參數傳給 system call:
以 write 為例子, 將傳進來的參數存到 %ebx, %ecx, 然後在執行 sys_call_table 裡頭的 function 之前 push 到 stack, 請參閱 sys_call。
文字敘述很簡單 (所以通常被稱做嘴炮), 把它變成程式碼就困難些了。
不過後來找到這篇的實作方法:
Effective Use of ARM Cortex-M3 SVCall
我想試試看這個作法。
好了, 該輪到 cm3 的
asm_func.S L39 ~ 79 就是在處理 system call 的部份, 有些說明請參考以下圖片, 呃 ... 我也不願意這麼做, 實在是太沒質感了, 應該畫個漂亮的圖才是, 有人願意幫忙嗎? 裡頭涉及到 context switch, 會有點複雜。
get_ticks() 是 system call, 將 {sys_get_ticks(), arg} 當成參數傳給 service_call(), service_call() 會執行 svc 觸發 svc exception, 再來便是上圖所敘述從 svc_isr 開始到返回。
這邊需要知道 cm3 c function 和組合語言如何傳遞參數, r0~r3 用來傳遞參數, 如果有第五個參數, 就要用 stack 來傳遞, 返回值則存在 r0。這裡同樣會有 context 的切換, 所以如果沒搞懂 context switch 如何實作, 這邊應該也是看不懂, 金字塔知識就是這樣堆積起來的。
程式若用上兩個 stack 會簡單點, 但這麼直白的程式, 比較好理解整個來龍去脈, 裡頭有著 user process, kernel code 的 stack 切換, 可以了解到一個 system call 的複雜, 和一般的 function call 可是有本質上的不同。
三個麻煩順利解決 (你說麻煩一沒解決是吧, 管他的, 做出來最重要, 美感的話再說了), 痛快。
system call 和 function call 有什麼不同呢? Expert C Programming a.4 提到了這個面試題目, 還很好心地給了答案:
Library Call | System Call |
The C library is the same on every ANSI C implementation | The systems calls are different in each OS |
Is a call to a routine in a library | Is a call to the kernel for a service |
Linked with the user program | Is an entry point to the OS |
Executes in the user address space | Executes in the kernel address space |
Counts as part of the "user" time | Counts as part of the "system" time |
Has the lower overhead of a procedure call | Has high overhead context switch to kernel and back |
There are about 300 routines in the C library libc | There are about 90 system calls in UNIX, (fewer in MS-DOS) |
Documented in Section 3 of the UNIX OS manual | Documented in Section 2 of the UNIX OS manual |
Typical C library calls: system, fprintf, malloc | Typical system calls: chdir, fork, write, brk |
沒有留言:
張貼留言
使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。
我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。