基于X86平臺的簡(jiǎn)單多任務(wù)內核的分析與實(shí)現
摘要:描述了一個(gè)簡(jiǎn)單多任務(wù)內核的設計和實(shí)現方法。分析了該簡(jiǎn)單內核的基本結構和加載運行的基本原理,然后描述了其被加載進(jìn)機器RAM中以及兩個(gè)任務(wù)進(jìn)行切換的運行方法。
本文引用地址:http://dyxdggzs.com/article/201610/305817.htm0 引言
當提到多任務(wù)時(shí),人們便會(huì )聯(lián)想到Mac OS、Linux、Windows等操作系統。通常情況下,若在操作系統下運行多任務(wù),是由操作系統負責管理和調度各個(gè)任務(wù)的。本文通過(guò)分析一個(gè)簡(jiǎn)單的多任務(wù)內核,能夠便于更容易地理解操作系統的任務(wù)管理機制,以及可以理解計算機系統是如何啟動(dòng)的。
1 多任務(wù)程序的結構
本文實(shí)現的簡(jiǎn)單多任務(wù)內核,主要由兩個(gè)文件構成:一個(gè)是使用as86語(yǔ)言編制的引導啟動(dòng)程序,主要用于在計算機系統加電時(shí),將內核代碼從啟動(dòng)盤(pán)加載到內存中;另一個(gè)便是使用GNU as匯編語(yǔ)言編寫(xiě)的內核程序,其中實(shí)現兩個(gè)運行在特權級2上的任務(wù)可在時(shí)鐘中斷控制下相互切換運行,并可通過(guò)系統調用在屏幕上實(shí)現字符顯示。
2 多任務(wù)內核工作的啟動(dòng)程序原理
計算機系統加電啟動(dòng)后,會(huì )把啟動(dòng)程序從啟動(dòng)盤(pán)的第一個(gè)扇區加載到物理內存0x7c00位置開(kāi)始處,之后把執行權交給0x7c00初開(kāi)始運行啟動(dòng)程序。
啟動(dòng)程序的主要功能是將軟盤(pán)或者鏡像文件中的內核程序加載到內存的某個(gè)指定位置,實(shí)現這個(gè)目的的方法是利用ROS BIOS中斷int 0x 13,把軟盤(pán)或者鏡像中的內核代碼讀入到內存,然后再把這段內核代碼移動(dòng)到內存0開(kāi)始處。最后設置控制寄存器CR0中的開(kāi)啟保護運行模式標志,并跳轉到內存0處開(kāi)始執行內核代碼。啟動(dòng)程序在內存中移動(dòng)內核代碼的示意圖如圖1所示。

將內核代碼移動(dòng)到物理內存0開(kāi)始處的主要原因是這是GDT表時(shí)可以簡(jiǎn)單一點(diǎn)。但是,不能讓啟動(dòng)程序把內核代碼從軟盤(pán)或映像文件中直接加載到內存0處,因為加載操作需要ROM BIOS提供中斷過(guò)程,而B(niǎo)IOS使用的中斷向量表正處于內存0開(kāi)始處。若直接把內核代碼加載到內存0處,那么,BIOS中斷過(guò)程將不能正常運行。
3 內核程序
3.1 初始化任務(wù)
內核程序運行在32位保護模式下,初始化階段主要包括重新設置GDT表,設置系統定時(shí)器芯片,重新設置IDT表并且設置時(shí)鐘和系統調用中斷門(mén)。內核示例中所有代碼和數據段都對應到物理內存同一個(gè)區域上,即從物理內存0開(kāi)始的區域。在虛擬地址空間中內核程序的內核代碼和任務(wù)代碼分配圖如圖2所示。

3.2 啟動(dòng)第一個(gè)任務(wù)
特權級0的代碼不能直接把控制權轉移到特權級2的代碼中執行,但可以使用中斷返回操作來(lái)實(shí)現,因此當初始化GDT、IDT和定時(shí)芯片結束后,就利用中斷返回指令I(lǐng)RET來(lái)啟動(dòng)第一個(gè)任務(wù)。
具體的實(shí)現方法是在初始堆棧init stack中人工設置一個(gè)返回環(huán)境,即把任務(wù)0的TSS段選擇符加載到任務(wù)寄存器TR中,LDT段選擇符加載到LDTR中以后,把任務(wù)0的用戶(hù)棧指針和代碼指針以及標志寄存器值壓入棧中,然后執行中斷返回指令I(lǐng)RET。該指令會(huì )彈出堆棧上的堆棧指針作為任務(wù)0用戶(hù)棧指針,恢復假設的任務(wù)0的標志寄存器內容,并且彈出棧中代碼指針?lè )湃隒S:EIP寄存器中,從而開(kāi)始執行任務(wù)0的代碼,以完成從特權級0到特權級3代碼的控制轉移。
3.3 兩個(gè)任務(wù)的切換
內核程序將定時(shí)器芯片的通道0設置成每經(jīng)過(guò)10 ms就向中斷控制芯片發(fā)送一個(gè)時(shí)鐘中斷請求信號,這樣,每個(gè)10 ms將會(huì )切換運行的任務(wù)。PC的ROM BIOS開(kāi)機時(shí)已經(jīng)在定時(shí)器芯片中把時(shí)鐘中斷請求信號設置成中斷向量8,因此需要在中斷8的處理過(guò)程中執行任務(wù)切換操作。
每個(gè)任務(wù)在執行時(shí),會(huì )首先把一個(gè)字符的ASCII碼放入寄存器AL中,然后調用系統中斷int 0x80,而該系統調用處理過(guò)程會(huì )調用一個(gè)簡(jiǎn)單的字符寫(xiě)屏子程序。在顯示過(guò)一個(gè)字符后,任務(wù)代碼會(huì )使用循環(huán)語(yǔ)句延遲一段時(shí)間,然后又跳轉到任務(wù)代碼開(kāi)始處繼續循環(huán)執行,直到運行了10 ms而發(fā)生了定時(shí)中斷,從而代碼會(huì )切換到另一個(gè)任務(wù)去運行。
目前,該內核示例已經(jīng)在Bochs模擬軟件中運行測試過(guò),測試結果如圖3所示。

4 結語(yǔ)
本文分析了一個(gè)基于X86平臺的簡(jiǎn)單多任務(wù)內核的基本結構和加載運行原理,描述了其被加載進(jìn)機器RAM中的基本思路,同時(shí)給出了兩個(gè)任務(wù)進(jìn)行切換的運行方法。其主要目的是理解操作系統的啟動(dòng)加載過(guò)程。
附:本文的啟動(dòng)代碼及內核代碼如下:







評論