Linux內核0.12——從一個簡單的多任務內核實例學習保護模式

《Linux內核完全剖析——基於0.12內核》(趙炯著)P.140

/******引導啓動程序boot.s******/

此程序僅能加載長度不超過16個扇區的head代碼,並且直接使用BIOS默認設置的中斷向量號
首先利用BIOS中斷把內核代碼加載到內存0x10000處,然後移動到內存0處
最後進入保護模式,並跳轉到內存0開始處繼續運行
把內核代碼移動到物理內存0開始處的主要原因是爲了設置GDT表時可以簡單一些,但是我們不能直接將內核代碼加載到內存0處,因爲加載操作需要使用BIOS提供的中斷過程,該中斷向量表正處於內存0開始的地方

boot.s的流程如圖:


說明如下:
1、加載內核代碼到內存0x10000時,需要利用BIOS中斷int 0x13功能2,DH爲磁盤號,DL爲驅動器號,CH爲10位磁道號低8位,CL爲位6、7磁道號高2位,ES:BX=0x1000:0爲緩衝區位置,AH爲讀扇區功能號,AL爲需讀扇區數

2、IDT爲中斷描述符表,它將每個異常或中斷向量分別與它們的處理過程相聯繫,IDT是由8字節長描述符組成的一個數組,最多可有256箇中斷描述符,IDT可以駐留在線性地址空間的任何地方,使用IDTR寄存器可以定位IDT的位置,IDT描述符分爲中斷門、陷阱門和任務門三種描述符,異常與中斷處理的操作如圖:


3、GDT爲全局描述符表,當任務發生切換時,LDT會更換成新的LDT,但是GDT並不會改變,因此,GDT所映射到一半虛擬地址空間是系統中所有任務共有的,即系統中所有任務共享的段由GDT來映射,每個系統必須定義一個GDT,並可用於系統中所有程序或任務。GDT本身並不是一個段,而是線性地址空間中的一個數據結構,處理器並不使用GDT中的第一個描述符,GDT必須含有LDT的段描述符,即每個LDT都必須在GDT中有一個段描述符和段選擇符,此引導程序中設置的GDT表長度爲2KB,可容256個描述符項,線性基地址在0x7c0段的偏移gdt處。本程序共設置三個段描述符,段描述符0不用,段描述符1設置爲:0x00c09a00000007ff,段描述符2設置爲:0x00c09200000007ff,段描述符64位二進制的通用格式如圖:

根據對各位的置數,可以將兩個段描述符設置爲代碼描述符和數據描述符(此時S=1)

/××××××××多任務內核程序head.s××××××××/

head.s包含了32位保護模式初始化設置代碼、時鐘中斷代碼、系統調用中斷代碼和兩個任務的代碼,在初始化完成之後程序移動到任務0開始執行,並在時鐘中斷控制下進行任務0和1之間的切換操作,整個head.s的流程如圖:


說明如下:

1、多任務的初始化:如果要使用多任務機制,軟件初始化代碼必須至少設置一個TSS及其相應的TSS段描述符,TSS描述符應和LDT段描述符一樣存入GDT中,head.s中的任務0、1分別將其的TSS0、TSS1存入了GDT

2、段選擇符:是段的一個16位標識符,段選擇符指向段描述符表中定義段的段描述符,段選擇符有三個字段:請求特權級、表指示標誌、索引值,在head.s中,共有這麼幾個段選擇符:屏幕顯示內存段選擇符0x18,任務0的TSS段選擇符0x20,任務0的LDT段選擇符0x28,任務1的TSS段選擇符0x30,任務1的LDT段選擇符0x38,任務0的LDT、TSS段選擇符在執行任務0時的人工堆棧操作中將其加載到LDTR和任務寄存器TR中,屏幕顯示內存段選擇符在執行顯示字符程序中存入GS寄存器中,任務1的LDT段選擇符被存入其TSS段選擇符中,在定時中斷程序中進行TSS0和TSS1的切換

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