進程狀態保存與恢復數組
特權級變換數據結構
再次理解TSS 、堆棧函數
從外環進入內環(特權級發生變化)時,如何訪問TSS?堆棧的變化指針
P193頁,中斷髮生的開始,ESP的值是剛剛從TSS裏面渠道的進程表A中regs的最高地址,上述過程的實現代碼在哪?rest
造成進程的必要考慮。咱們須要一數據結構來記錄一個進程的狀態,這樣方便進行進程切換時,能夠保存原來的進程狀態。進程被掛起時就將信息寫入這個數據結構,進程從新啓動時,這裏的信息就被從新讀取。進程
因爲進程和進程調度運行在不一樣層級上,這裏爲了簡單,讓全部任務運行在ring1,讓進程切換運行在ring0。ip
一個簡單的進程切換情形,一個進程在執行時,發生了時鐘中斷,特權級從ring1跳轉到ring0,開始執行時鐘中斷處理程序,中斷處理程序這時調用進程調度模塊,指定下一個應該運行的進程,當中斷處理程序結束時,下一個進程準備就緒並開始運行,特權級又從ring0跳轉回ring1:內存
爲了實現這種進程切換,須要如下模塊:it
須要保存的是那些可能會發生改變的量,從寄存器和內存兩個角度考慮,由於不一樣進程之間的內存是互不干涉的,可是CPU卻只有一個,不一樣的進程共用同一個CPU的一套寄存器,因此應該保存寄存器的值,準備進程被恢復時使用。基礎
保存的是處理機狀態信息,包括
a. 進程當前暫存信息;
b. 下一條指令地址信息;
c. 進程狀態信息;
d. 過程和系統調用參數及調用地址信息.
爲了保證進程狀態完整不被破壞,在進程剛剛掛起時保存全部寄存器的值。保存的方法爲push(即存到PCB中),或者是push ad.
這些代碼應該寫在時鐘中斷例程的最頂端,以便中斷髮生時立刻被執行。
保存使用的是push,恢復用的即是pop,將寄存器的值都恢復,而後執行指令iretd,回到對應進程。
保存進程狀態的東西,即進程表,亦或進程控制塊(PCB)。
因爲會有對個進程,因此會有多個進程表,造成一個進程表數組。
進程表是描述進程的,必須獨立於進程以外。
分析代碼
358行:將esp更改,即讓esp指向進程表,p_proc_ready指針指向的是下一個要啓動進程的進程表地址。
359行:設置ldt,esp+p_ldt_sel即指向進程表中的ldt_sel,可知在執行restart以前對ldt_sel進行了初始化
360、361:將進程表的第一個成員的regs末地址賦值給TSS中的ring0堆棧指針域(esp)。下一次執行中斷時。esp將變成regs的末地址。
這裏直接使用iretd
首先在i8259.c的init8259a中打開中斷。
設置EOI使中斷持續不停的發生
爲了使中斷能夠被觀察,這裏經過改變屏幕第0行,第0列的字符來表示中斷在運行。中斷髮生時會一直變成下一個
運行結果以下所示,此時截圖到了6
爲何不用disp_str,而是直接使用move寫顯存?
這是由於disp_str會影響不少寄存器,進而可能致使對進程的影響。上面的改變al從結果上時沒有產生改變的但爲了不沒必要要的錯誤,咱們仍是將全部的寄存器都壓入堆棧,執行以後再恢復。
前面咱們知道,進程調度發生時,僅僅切換到進程表是不夠的,爲了防止進程表相應的棧的有關信息被破壞,咱們還要繼續切換棧,這時候就要用到內核棧了。
切換到內核棧的方法很是簡單,只需在原代碼的基礎上增長兩行move便可,切換的時機爲寄存器剛被壓入堆棧之後(壓入堆棧後就當即跳轉到內核棧,不然此時進行堆棧操做會影響進程表存儲的信息),以及對tss.esp0賦值以前(不然下次中斷就直接內核棧了)。
這裏增長了中斷顯示消息"",因此會在下面顯示「」,以下圖所示
爲了讓中斷髮生時,還能繼續接受中斷,咱們須要進行必定的修改。
CPU在響應中斷時,會自動的關中斷,這是咱們要人爲打開,因此要使用指令sti打開中斷,並在離開內核棧前用cli關閉中斷;
爲了實驗的方便,咱們須要中斷處理的時間足夠長,因此增長了延時函數
這樣會帶來一個問題,即當一次中斷未完成時,另外一箇中斷就發生,致使永遠沒法執行到中斷處理程序的結尾,做用於顯示上就是打印一個A0x0後一直打印^。
而且因爲一直在壓棧而無出棧,會致使堆棧溢出。
解決這個問題,須要讓中斷處理程序知道本身是否在嵌套執行。設置一個全局變量來實現,中斷處理程序執行時自加,結束時自減。這裏設置爲初始值爲-1.當結果不爲0時,說明未處理完髮生了中斷,這時直接跳到最後,結束新的中斷。
運行結果以下,可知打印^的速度變慢了,說明不少程序執行了inc byte後並無執行disp_str。中斷重入已經解決,因此無需延時函數,最後運行結果如最下方所示
取到進程表A中regs的最高地址的代碼
實現的代碼其實沒有,是CPU本身實現的
將proc.c中的對應函數改成上述,即調用後指向下一個進程,若是進程爲最後一個,返回到進程表的第一個。
在a的地方,進行調用後面加入第二句話。在C處使用延時函數。