Lab1:系統軟件啓動過程
bootloader的啓動
我們的操作系統鏡像文件uroce.img
保存在硬盤disk上,其中前512個字節是引導扇區,存放了一個小軟件bootloader
,而後面存放的則是ucore內核文件。
當CPU加電啓動時,將會默認執行位於固件上的BIOS程序(姑且認爲它在內存中),當BIOS完成硬件自檢後將選擇系統盤當中引導扇區的512個字節加載到內存當中,此時CPU跳轉到該位置執行bootloader
。
那麼bootloader
完成了一些什麼事情呢?
-
開啓保護模式
在Intel 80836運行模式中,爲了向下兼容8086,在啓動時實際上運行的時實模式。實模式下,只有20根地址線被使用,物理地址的大小隻有1MB,此時程序訪問的地址就是實際的物理地址。顯然,這是不利於操作系統的安全的,因此我們需要保護模式。
首先,打開A20開關,啓用第20根地址線,可用物理內存達到4GB。
隨後,初始化全局描述符表GDT,它是段描述符表之一,顧名思義就是段描述符的數組,它的首地址在寄存器GDTR當中。
那什麼是段描述符呢?它主要包含3個方面的內容:段基址Base、段大小Limit、訪問標誌位。結合我們學過的分段機制,我們可以將一個程序的邏輯地址分爲兩部分:段選擇子Selector和偏移Offset。根據
GDT[Selector].Base
我們就能獲取到程序的某一段(代碼段、數據段…)在物理內存中的位置。通過分段機制,我們將邏輯地址轉化爲了線性地址(在這裏也是物理地址)。
-
加載ucore OS操作系統
bootloader
的一個重要作用就是加載OS到內存當中。ucore此時是一個可執行文件,以ELF文件格式存儲在硬盤上。bootloader
的功能就是讀取硬盤,解析ELF文件,將操作系統內核分段加載到內存當中的各個部分,隨後將控制權交給內核來執行。
操作系統開始運行
我們的系統不僅有CPU,還有許多其它的外設。如何使得外設也能夠爲操作系統所用呢?這就涉及到中斷的初始化。操作系統將構建一個中斷向量表IDT:保存了各個中斷服務例程的入口地址。
而我們的中斷服務例程(中斷處理函數)是事先寫好在操作系統內核的,在加載過程中只需將其地址複製到IDT當中即可。當中斷被觸發時,根據產生的中斷向量查找中斷向量表,就可以陷入內核態執行相應的程序。
當完成這些工作之後,操作系統就可以繼續執行後面的代碼了。Lab1當中的ucore將會打印一段字符串,隨後進入while死循環當中。