操作系统开发系列—13.g.操作系统的系统调用 ●
在我們的操作系統(tǒng)中,已經(jīng)存在的3個進程是運行在ring1上的,它們已經(jīng)不能任意地使用某些指令,不能訪問某些權(quán)限更高的內(nèi)存區(qū)域,但如果一項任務需要這些使用指令或者內(nèi)存區(qū)域時,只能通過系統(tǒng)調(diào)用來實現(xiàn),它是應用程序和操作系統(tǒng)之間的橋梁。
所以,一件事情就可能是應用程序做一部分,操作系統(tǒng)做一部分。這樣,問題就又涉及特權(quán)級變換。
很明顯,這已經(jīng)難不倒我們了,因為進程的切換就是不停地在重復這么一個特權(quán)級變換的過程。在那里,觸發(fā)變換的是外部中斷,我們把這個誘因換一下就可以了,變成"int nnn",一切就都解決了。
我們來實現(xiàn)一個叫做int get_ticks()的函數(shù),用這個函數(shù)來得到當前總共發(fā)生了多少次時鐘中斷。設(shè)置一個全局變量ticks,每發(fā)生一次時鐘中斷,它就加1,進程可以隨時通過get_ticks()這個系統(tǒng)調(diào)用來得到這個值。
見syscall.asm:
_NR_get_ticks equ 0 ; 要跟 global.c 中 sys_call_table 的定義相對應! INT_VECTOR_SYS_CALL equ 0x90global get_ticks ; 導出符號bits 32 [section .text]get_ticks:mov eax, _NR_get_ticksint INT_VECTOR_SYS_CALLret這里將系統(tǒng)調(diào)用對應的中斷號設(shè)為0x90,它只要不和原來的中斷號重復即可。
馬上來定義INT_VECTOR_SYS_CALL對應的中斷門,protect.c:
PUBLIC void init_prot() { ...init_idt_desc(INT_VECTOR_SYS_CALL, DA_386IGate,sys_call, PRIVILEGE_USER); ... }?這樣我們就將第INT_VECTOR_SYS_CALL號中斷與sys_call對應起來了。這里的call [sys_call_table+eax*4](調(diào)用的是sys_call_table[eax]),與irq_table類似,sys_call_table是一個函數(shù)指針數(shù)組,每一個成員都指向一個函數(shù),用以處理相應的系統(tǒng)調(diào)用。
extern sys_call_tableglobal sys_callsys_call:call savesticall [sys_call_table + eax * 4]mov [esi + EAXREG - P_STACKBASE], eaxcliret前面eax已被賦值為_NR_get_ticks(即0),而sys_call_table[0]已經(jīng)初始化為sys_get_ticks,所以call [sys_call_table+eax*4]這一句調(diào)用的便是sys_get_ticks。
mov [esi+EAXREG-P_STACKBASE],eax是把函數(shù)sys_call_table[eax]的返回值放在進程表中eax的位置,以便進程P被恢復執(zhí)行時eax中裝的是正確的返回值。
現(xiàn)在可以在進程中添加調(diào)用get_ticks的代碼了:
void TestA() {int i = 0;while (1) {get_ticks();disp_str("A");disp_int(i++);disp_str(".");delay(1);} }別忘了在kernel.asm和syscall.asm中導入和導出相應符號。
修改
void TestA() {int i = 0;while (1) {disp_str("A");disp_int(get_ticks());disp_str(".");delay(1);} }運行如下,第一個是A0x0,第二個是A0x27,兩次之間的“#”恰好是39個,我們的get_ticks一切正常:
?
【源碼】
轉(zhuǎn)載于:https://www.cnblogs.com/joey-hua/p/5487034.html
總結(jié)
以上是生活随笔為你收集整理的操作系统开发系列—13.g.操作系统的系统调用 ●的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: way.js - 轻量级、持久化的双向绑
- 下一篇: ...python の 学习