Linux系統內核main函數執行之前


1、linux是一個操作系統在機器加電后,需要從硬件通過一個引導程序加載os kernel,那么在os kernel的main函數運行之前,都發生了什么呢?

(1)引導BIOS(存儲在ROM芯片中,ROM:只讀存貯器,現在一般為閃存)的啟動(准備實模式下的中斷向量表和中斷服務程序)

實模式:Intel80x86系列的一種cpu運行模式,特點,20位地址尋址(1MB),可直接訪問BIOS和周邊的硬件,沒有硬件支持的實時多任務和分頁機制。

BIOS任務:把os 加載到RAM(隨機存取存儲器,也就是常見的內存條)

所有的cpu在加電時強行進入16位實模式,此時cpu的一些特殊值:

CS:0xF0000,IP:0xFFF0 所以起始地址為CS:IP   =   0xFFFF0也就是BIOS的地址。

CS:代碼段寄存器

IP:指令指針寄存器(IP對應16位,EIP對應32位,RIP對應64位)

指令的地址:代碼段其實地址+指令段內偏移地址 = CS + IP

中斷向量表的位置:0x00000 ~ 0x003FF (一共1kb):一共256個中斷向量(CS:IP),每個4B(CS:2B;IP:2B)

BIOS數據區:0x00400 ~ 0x004FF

中斷服務程序:0x0E50B ~ 0x0FFFE

中斷int

(2)加載第一部分kernel代碼(bootsect)

BIOS收到int 0x19,轉到中斷服務程序0x0E6F2(啟動加載服務程序的入口地址):把第一扇區的512B代碼加載到內存制定位置(0x07C00)

(3)加載第二部分代碼:

首先規划內存,然后拷貝自身從0x07C00 到0x90000

(DS/ES/FS/GS/SS段寄存器,SP棧頂指針)

然后是int 0x13,將setup.s這一部分代碼加載到內存0x90200處。

bootsect和setup.s是緊緊連在一起的此時SS:SP的值是0x9FF00

(4)加載系統模塊

bootsect利用int 0x13加載系統模塊,執行加載任務的主要程序read_it ,將約120KB的內容加載值0x10000(SYSSEG)處

然后確認一下根設備號,根文件系統設備(root device):系統中利用工具做出一個文件系統並加載至本機。

(5)通過jumpi 0,SETUPSEG:跳轉至setup.s(0x90200)處,執行setup

利用BIOS提供的中斷服務程序從設備讀取機器系統數據,從0x41 和 0x46 處讀取 硬盤參數表1 和 硬盤參數表2 ,分別放置在

0x90080 和 0x90090 處 

系統的數據加載到內存:0x90000-0x901FD total:510B

開始實模式到保護模式的變化

(6)關閉中斷(CPU IF位:0)

開中斷和關中斷(cli 和 sti)

復制內核到內存的0x00000處(釋放BIOS的中斷向量表和中斷服務程序,然后移動內核)

設置中斷描述符表 和 全局描述符表 (IDT 和 GDT),

中斷描述符表寄存器(IDTR)

全局描述符表寄存器(GDTR)系統中唯一存放段寄存器內容的數組,配合保護模式下的尋址

************************************************************************************************

存放任務的局部描述符表(LDT)地址 和 任務狀態段(TSS)地址 完成進程各段的尋址,進城現場的保護與恢復

GDTR標示GDT的入口,一般用LGDT將GDT基地址加載到GDTR

IDT:中斷服務程序的入口地址。

IDTR:保存IDT的起始地址。(LIDT指令完成)

*************************************************************************************************

(7)打開A20,實現32位尋址(否則,即在16位模式下,超范圍尋址將導致尋址回滾)

  32位尋址:最大尋址空間4GB

執行head.s

首先認識一下可編程中斷控制器:8259A:單片可管理8級向量優先級中斷(可聯級,最多管理64級向量中斷)

int 0x00 ~ int 0x1F   內部中斷(不可屏蔽) 和 異常中斷

保護模式下:IRQ0x00 ~ IRQ0x0F 對應中斷號:int 0x20 ~ int 0x2F

設置保護模式的代碼:

mov ax,#0x0001

lmsw ax

此時cr0寄存器第0位:PE置1

跳轉到head.s入口結束setup開始執行head文件。

注:x87:數學協處理器,外置可選(從486之后一般改為內置)。

將head.s 匯編成目標代碼,c語言kernel編譯成目標代碼,連接成system模塊。    

其中head:

25KB + 184B

head在0x000000位置創建也目錄表,頁表,緩沖區,GDT,IDT(占用覆蓋head已經執行過的代碼)

內核起始位置0x000000 _pg_dir (頁表目錄起始位置)

重建一套GDT,因為源GDT內存位置將被覆蓋。

檢查數學協處理器

最后的准備:

L6標號和main函數入口地址壓棧,L6是main函數異常退出時的程序轉接點:程跳轉到setup_paging去建立分頁機制。

一頁:4KB

Main函數入口:0x064b8

全局描述符表:0x05cb8

中斷描述符表:0x054b8

剩余184B:0x05400

軟盤緩沖區:0x05000

頁表3到頁表0的起始:0x01000 0x03000 0x02000 0x01000

頁表目錄:0x00000

Pg位CR0寄存器第31位:控制分頁。

CR3寄存器:分頁機制虛擬地址到物理地址的映射。

然后開始調用main。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM