一個小的OS內核,一些感受,一些總結。

 
前幾天剛讀了《Bran的內核開發指南》,感覺有些收穫。這裏簡單總結一下。
首先介紹下我的環境:
DJGPP,NASM [Windows]
VMWare WorkStation.(上跑RedHat Linux)
在將一個編譯好的簡單kernel運行的時候,用的是VMWare上虛擬的軟盤。至於怎樣在軟盤上裝grub等,不提。
下面說下幾點體會:
1.對於一個整個系統,或者叫一個整個的工程,一般都是有若干個小的部分組成的。以這個kernel爲例,爲了生成最終的一個kernel.bin,需要編寫若干個.c文件和一個.asm文件。在分別將這些文件編譯成.o後,最終需要一個ld的過程。從最終文件來看,這些各組成文件中的符號應該是全局惟一的,因爲他們最終都會在kernel.bin中存在。以前在學習c的時候,講到關鍵字extern,說它的作用是聲明一個變量或者函數在另外一個模塊中定義,現在終於體會到了是怎麼一回事。也從全局的角度來看,對於.bin的貢獻(^_^).asm.c是相同的。只是.asm只需一個nasm,而.c需要預處理,編譯,彙編的過程而已。
2.在過程中,曾遇到這樣一個問題:我在DJGPPgcc了那些.c文件,但是我卻在RH Linux中用ld,結果總是出現某些符號爲定義的錯誤。找過去,找過來,最終發現一個問題。在DJGPPGCC生成的文件是COFF格式,而RH LINUX下的LD需要的是ELF格式。我猜測,因爲格式的不同,ELF格式中對於.C的函數和變量符號在彙編後,在.S中是用本身的符號表示的,而不做變換。如.C中有函數ABC(),在編譯後的.S中也以符號ABC表示;而COFF格式中對於.C的函數和變量符號在彙編後,在.S中會對他們的符號作些變換,具體是在前面加一個下畫線。例如:.C中的函數ABC()在編譯後的.S中會以符號_ABC表示。所以,當我換在WINDOWS CMD下,用LD鏈接後,沒有出現問題。這時用的LD應該就是以COFF格式輸入的。
3.在生成了KERNEL.BIN後,COPY到軟盤下時,要注意:BOOT/GRUB下面的STAGE1,2的訪問權限要有X(試試知道的)
4.在彙編和C間傳遞參數用棧就可以了。並且,可以定義結構來表示棧中的內容,但要主要棧中內容的順序和結構的順序。
對於OS內核,有些感受:
5.正如MULTIBOOT規範中所講,一個OS的內核的格式應該可以是操作系統中可以運行的文件的格式,入A.OUTELF等。爲了能夠引導不同格式的內核,也及可以利用MULTIBOOT,那麼就必須在內核文件的開頭或者某些特殊位置定義某些固定的變量。如MAGIC等。
6.接上,既然內核可以是一般格式的可執行文件。那麼它就可以象應用程序那樣使用系統的內存,該文件也可以定義若干的數據結構。只是,爲了滿足硬件對於操作系統的支持,需要把這些數據結構的地址,大小等加載到某些特定功能的寄存器。GDT的地址和大小限制需要一個數據結構來表示,該結構的地址需要被LOADGDTR中,類似的還有IDTIDTR.
7.IDT中保存了若干的中斷號以及中斷服務程序的地址後,也可以對它們的映射關係做改變。當然,對於開始的32箇中斷(異常)是保留的,後面的可以自己映射。對於這裏,以前一直不是很理解,現在簡單總結一下中斷。當一箇中斷源(如鍵盤,系統時鐘)到來時,在8259對它們進行優先級判斷等操作後通知CPUCPU在得到它們的中斷號後,通過IDTR得到IDT的基地址,然後用中斷號取出距離IDT若干距離的ISR的地址,並轉到該ISR運行。注意,這個IDTR是我們用指令LIDT寫入的。其實,從這個KERNEL來看,我們就只需加載GDTRIDTR,以及提供一些映射就可以了。其他的,CPU會在遇到某種情況時自己找到該運行的程序。

 上面的東西,部分是我自己猜測的,希望各位看官能夠指出其中的錯誤。感謝萬分。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章