日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > windows >内容正文

windows

一个操作系统的实现(1)

發(fā)布時(shí)間:2025/3/18 windows 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一个操作系统的实现(1) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一個(gè)操作系統(tǒng)的實(shí)現(xiàn)

說(shuō)明:本文是一個(gè)簡(jiǎn)單的學(xué)習(xí)記錄,不是全面給大家提供學(xué)習(xí)的文章,文章內(nèi)容均代表作者的個(gè)人觀點(diǎn),難免會(huì)有錯(cuò)誤。轉(zhuǎn)載請(qǐng)保留作者信息。

?????????????????????????????????????????????????????????????????????????????????????????????????????????2010/11/20?

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?sylar_xiong

?????????????????????????????????????????????????????????????????????????????????????????? MSN& Email:cug@live.cn

?

準(zhǔn)備:UbuntuOS,? 虛擬機(jī)(用于調(diào)試OS內(nèi)核),這個(gè)新OS是一個(gè)簡(jiǎn)單的,常用的OS,以Intel I32為例(他幫我們完成了很多功能,例如中斷/保護(hù)模式/特權(quán)級(jí))。

?

首先需要掌握幾個(gè)基本概念:

1?系統(tǒng)的啟動(dòng)順序

?????? 系統(tǒng)會(huì)首先運(yùn)行boot(實(shí)模式), 然后運(yùn)行Loader,最后運(yùn)行kernel(假設(shè)為微內(nèi)核,加載文件系統(tǒng),MM,shell等模塊)。上個(gè)圖:

啟動(dòng)階段

完成的工作

說(shuō)明

位置

?

1 Boot.bin

加載loader進(jìn)內(nèi)存

只有512k

位于硬盤或者軟盤的第一個(gè)扇區(qū)

?

2 Loader.bin

加載內(nèi)核,啟動(dòng)保護(hù)和分頁(yè)

?

?

?

3 Kernel.bin

?

?

?

?

?

?

2?保護(hù)模式

?????? 系統(tǒng)啟動(dòng)的時(shí)候是實(shí)模式,在loader階段實(shí)現(xiàn)實(shí)模式向保護(hù)模式的跳轉(zhuǎn)。

?????? 首先看一下實(shí)模式: 8086的地址總線為20位,物理地址=段×16+offset 所以最大可以尋址1M的內(nèi)存空間(2的20次方)。在實(shí)模式下,段0xXXXXh表示0xXXX0h開始的一段內(nèi)存區(qū)域。

?????? 其次看一下地址的概念:我們平時(shí)調(diào)試程序的時(shí)候看到的地址均為logicaladdress,例如地址A等于0x40008000h, OS尋址的時(shí)候首先會(huì)根據(jù)GDT/LDT將A轉(zhuǎn)化為linear address A’ , 這就是所謂的段地址轉(zhuǎn)化。 ?接著A’會(huì)根據(jù)頁(yè)表轉(zhuǎn)化為A’’,這個(gè)A’’就是真正的physical address所在了。總結(jié)一下也就是:logical address -> linear address -> physical address(實(shí)際上我吧第一次跳轉(zhuǎn)理解為段尋址,第二次跳轉(zhuǎn)理解為頁(yè)尋址)

?????? 保護(hù)模式的尋址方式為:

描述符1包括:

段基址

段界限

屬性

一般為全局段

描述符2包括:

段基址

段界限

屬性

?

LDT1

?

?

?

和進(jìn)程相對(duì)應(yīng)

LDT2

?

?

?

?

PED

?

?

?

分頁(yè)機(jī)制

PTD

?

?

?

?

GDT(每個(gè)GDT中包含很多描述符和LDT,每個(gè)描述符描述了一個(gè)段(可以是數(shù)據(jù)段,代碼段/堆棧段/系統(tǒng)段或者門描述符)的信息,包括段的基地址,界限和段的屬性。其中段的屬性包括段的特權(quán)級(jí)。GDT中還包含了很多指向LDT的描述符,每個(gè)LDT代表一個(gè)單獨(dú)的進(jìn)程,我們把一個(gè)單獨(dú)的進(jìn)程隨需要的各種數(shù)據(jù),例如數(shù)據(jù)段/代碼段/堆棧段封裝在一個(gè)LDT里面)

看一段簡(jiǎn)單的實(shí)模式跳轉(zhuǎn)到保護(hù)模式的代碼:

[section .gdt]???????????????????????????????????????? ??????// GDT段標(biāo)識(shí)

LABEL_GDT: descriptor????????? 0,???0,?????? 0;????? ?//GDT首地址

LABEL_DESC_CODE32:descriptor 0, 200, 0;

LABEL_VIDEO: descriptor0xb8000h, 0ffffh, DA_DRW;???? //顯存段基址為0xb80000h 段界限為offffh,屬性為該段在內(nèi)存中存在/為代碼段

?

SelectorCoderequ LABEL_DESC_CODE32 – LABEL_GDT

SelectorViedoequ LABEL_DESC_VIDEO – LABEL_GDT

?

[section .s16]

[BITS 16]????????????????????? //16位代碼

?????? Cli//關(guān)中斷

?????? //打開地址線A20
?????? jmp dword SelectorCode32:0? //跳轉(zhuǎn)到LABEL_SEG_CODE32的0位置處。

?

[section .s32]

[BITS 32]

LABEL_SEG_CODE32:

?????? Movax, SelectorVideo

?????? Movgx, ax????????? //gx為顯存段首地址?????

?

分頁(yè)機(jī)制補(bǔ)充:通過(guò)GDT,LDT得到線性地址后,會(huì)利用PED(頁(yè)目錄)和PTD(頁(yè)表),PED中每個(gè)表項(xiàng)指向了一個(gè)PTD,而一個(gè)PED中每個(gè)表項(xiàng)指向了一個(gè)世紀(jì)的4K物理地址。

同時(shí)應(yīng)該了解到,我們調(diào)試程序的時(shí)候看到的地址是線性地址,所以運(yùn)行同一個(gè)可執(zhí)行文件2次的地址和寄存器都是完全一樣的,事實(shí)上他們的物理執(zhí)行地址并不相同。

3?二進(jìn)制文件 or 可執(zhí)行文件格式

?????? 純二進(jìn)制文件:內(nèi)存映像和二進(jìn)制文件映像是一樣的。

?????? .bin文件: = loader.bin? =? COM文件:dos運(yùn)行的文件

?????? ELF文件:OS kernel的文件形式。他的結(jié)構(gòu)如下(例如kernel.elf):

文件開始處

結(jié)構(gòu)說(shuō)明

備注

?

Elf header

Elf文件頭,包含文件大小,屬性等

?

Program header1

數(shù)據(jù)段在文件中的位置和內(nèi)存中的位置

?

Program header2

代碼段從文件中到內(nèi)存中的映射關(guān)系

?

?

文件執(zhí)行的時(shí)候首先查看elf header,然后根據(jù)

Program headerN將每個(gè)段加載到內(nèi)存相應(yīng)的位置并執(zhí)行。

?

4?特權(quán)級(jí)

???????我首先假定內(nèi)核的level=0 系統(tǒng)服務(wù)的level=1 應(yīng)用程序的level=3。程序從一個(gè)代碼段轉(zhuǎn)移到另一個(gè)代碼段時(shí)(可能的情況是調(diào)用系統(tǒng)函數(shù)),需要考慮權(quán)限問(wèn)題,利用了CPL,DPL和RPL來(lái)判斷是否可以進(jìn)行代碼轉(zhuǎn)移。

?????? 利用call調(diào)用門實(shí)現(xiàn)一個(gè)低特權(quán)級(jí)的進(jìn)程訪問(wèn)高特權(quán)級(jí)的代碼段,利用ret指令實(shí)現(xiàn)高特權(quán)級(jí)到低特權(quán)級(jí)的跳轉(zhuǎn)。

?????? Jmp時(shí),不管長(zhǎng)跳轉(zhuǎn)還是短跳轉(zhuǎn)都一樣的實(shí)現(xiàn)。Call時(shí),長(zhǎng)跳轉(zhuǎn)需要比短跳轉(zhuǎn)額外保存一下當(dāng)前進(jìn)程的cs地址到堆棧段中(因?yàn)榉祷貢r(shí)需要知道要返回到哪個(gè)代碼段)。例如用戶進(jìn)程A(ring3)執(zhí)行時(shí)通過(guò)調(diào)用門訪問(wèn)系統(tǒng)進(jìn)程B(ring0)的代碼段(可以理解為一個(gè)系統(tǒng)函數(shù)調(diào)用),執(zhí)行完后返回,這個(gè)過(guò)程可以歸納如下:

1)?用戶進(jìn)程A將參數(shù),返回值,cs地址保存到LDT進(jìn)程A的堆棧段中。

2)?用戶進(jìn)程A的程序通過(guò)call調(diào)用門跳轉(zhuǎn)到系統(tǒng)進(jìn)程B中執(zhí)行。由于現(xiàn)在已經(jīng)是B中的代碼在執(zhí)行,所以相應(yīng)的使用的是B的堆棧段。同時(shí),A的堆棧段的位置ss和esp會(huì)保存到TSS(每個(gè)進(jìn)程一個(gè))

3)?B中相應(yīng)的代碼執(zhí)行完畢(對(duì)應(yīng)命令ret),執(zhí)行完畢后通過(guò)取出TSS中保存的A的堆棧段中的返回地址來(lái)返回A。

?

反過(guò)來(lái),由一個(gè)系統(tǒng)進(jìn)程(ring0)進(jìn)入用戶進(jìn)程(ring3)的關(guān)鍵在于,在ring0向ring3跳轉(zhuǎn)之前,手動(dòng)保存ring3進(jìn)程A的當(dāng)前cs,eip,ss,esp到A的ss中,然后調(diào)用命令retf,這個(gè)命令會(huì)自動(dòng)加載A的cs,eip,ss,esp到CPU寄存器,并跳轉(zhuǎn)開始執(zhí)行A。這就實(shí)現(xiàn)了ring0 toring3。

?

5?中斷和異常

?????? 中斷是一個(gè)計(jì)算機(jī)執(zhí)行的根本,進(jìn)程調(diào)度,鍵盤輸入等等都是中斷。保護(hù)模式下,中斷是通過(guò)IDT(中斷描述符表)來(lái)實(shí)現(xiàn)的,中斷發(fā)生時(shí),會(huì)在IDT中找到對(duì)應(yīng)的描述符,并轉(zhuǎn)到相應(yīng)的中斷處理函數(shù)處運(yùn)行。終端分為軟件中斷(通過(guò)int N命令實(shí)現(xiàn))和外部硬件中斷(例如時(shí)鐘中斷,鼠標(biāo)鍵盤中斷等)。

其中外部硬件中斷需要通過(guò)和CPU的INTR引腳相連的2個(gè)8258A芯片實(shí)現(xiàn)。

下面只討論保護(hù)模式下的中斷:

?????? 保護(hù)模式下,有一個(gè)中斷寄存器,指示了IDT的位置和IDT的大小。中斷分為3種類型:中斷門(運(yùn)行時(shí)關(guān)閉中斷,只能由內(nèi)核調(diào)用);陷阱門(運(yùn)行時(shí)不關(guān)中斷,只能由系統(tǒng)調(diào)用);系統(tǒng)門(在用戶態(tài)下,可以使用int3、into、bound 及int0x80四條匯編指令進(jìn)入系統(tǒng)門)

從深層次看一下中斷的過(guò)程:

1.CPU檢查是否有中斷/異常信號(hào)

CPU在執(zhí)行完當(dāng)前程序的每一條指令后,都會(huì)去確認(rèn)在執(zhí)行剛才的指令過(guò)程中中斷控制器(如:8259A)是否發(fā)送中斷請(qǐng)求過(guò)來(lái),如果有那么CPU就會(huì)在相應(yīng)的時(shí)鐘脈沖到來(lái)時(shí)從總線上讀取中斷請(qǐng)求對(duì)應(yīng)的中斷向量。

對(duì)于異常和系統(tǒng)調(diào)用那樣的軟中斷,因?yàn)橹袛嘞蛄渴侵苯咏o出的,所以和通過(guò)IRQ(中斷請(qǐng)求)線發(fā)送的硬件中斷請(qǐng)求不同,不會(huì)再專門去取其對(duì)應(yīng)的中斷向量。

2. 根據(jù)中斷向量到IDT表中取得處理這個(gè)向量的中斷程序的段選擇符

CPU根據(jù)得到的中斷向量到IDT表里找到該向量對(duì)應(yīng)的中斷描述符,中斷描述符里保存著中斷服務(wù)程序的段選擇符。

3.根據(jù)取得的段選擇符到GDT中找相應(yīng)的段描述符
CPU使用IDT查到的中斷服務(wù)程序的段選擇符從GDT中取得相應(yīng)的段描述符,段描述符里保存了中斷服務(wù)程序的段基址和屬性信息,此時(shí)CPU就得到了中斷服務(wù)程序的起始地址

?

?

6?最簡(jiǎn)單的文件系統(tǒng)FAT12

假設(shè)我們有一個(gè)硬盤,劃分為了2個(gè)分區(qū)C和D。C為FAT12,D為NTFS。下面僅僅看看C分區(qū)的結(jié)構(gòu)。從小到到依次為:扇區(qū),簇,分區(qū)。其中軟盤或硬盤第一個(gè)扇區(qū)被稱為引導(dǎo)扇區(qū)。

……

數(shù)據(jù)區(qū)

?

……

扇區(qū)n

根目錄

存放文件信息(包括文件名,修改時(shí)間,文件大小,文件內(nèi)容對(duì)應(yīng)的數(shù)據(jù)區(qū)索引)和目錄結(jié)構(gòu)

……

扇區(qū)19

扇區(qū)18

FAT2

?

……

扇區(qū)10

FAT1

對(duì)于文件大小大于512字節(jié)的文件來(lái)說(shuō),將一個(gè)文件對(duì)應(yīng)的所有扇區(qū)串聯(lián)起來(lái)。

……

扇區(qū)1

扇區(qū)0

引導(dǎo)扇區(qū)

?

一般而言,引導(dǎo)扇區(qū)存放boot.bin, boot..bin運(yùn)行的時(shí)候會(huì)尋找根目錄中的loader.bin文件,如果找到這個(gè)文件名,就會(huì)從數(shù)據(jù)區(qū)中將loader.bin取出加載到內(nèi)存相應(yīng)位置。

?

?

下面開始正文

一?一個(gè)操作系統(tǒng)的啟動(dòng)過(guò)程

???????1從硬盤或者軟盤的引導(dǎo)扇區(qū)(最大只能為512b,所以有了Loader.bin)開始啟動(dòng),引導(dǎo)扇區(qū)(boot.bin)完成的主要任務(wù)是從硬盤(或者軟盤,這里假設(shè)為FAT12格式的文件系統(tǒng))中的根目錄找到并加載Loader.bin到內(nèi)存0x90000h處并將控制權(quán)交給boader.bin(即跳轉(zhuǎn)到0x90000h處執(zhí)行)。

???????2loader.bin 首先在硬盤(軟盤中)查找并加載kernel.elf到內(nèi)存(具體的過(guò)程就是將kernel.elf中不同的段放到不同的內(nèi)存位置)

???????3Loader.bin中定義了GDT和一個(gè)GDT指向的代碼段(假設(shè)為L(zhǎng)ABEL_PM_START)。然后loader.bin執(zhí)行一系列匯編打開保護(hù)模式并最終通過(guò)jmp跳轉(zhuǎn)到LABEL_PM_START處。

???????4進(jìn)入保護(hù)模式之后,Loader.bin初始化各個(gè)寄存器,初始化堆棧,打開分頁(yè)機(jī)制(步驟為:首先獲取可用內(nèi)存信息,根據(jù)可用內(nèi)存信息初始化GTD中的頁(yè)目錄和頁(yè)表,此時(shí)的分頁(yè)機(jī)制還僅僅只是對(duì)等映射。)。

???????5loader將kernel.elf加載到物理地址

???????6由于kernel是一個(gè)elf文件,所以loader還需要把kernel.elf的不同段復(fù)制到指定的地方。此時(shí)的物理內(nèi)存情況為:

起始物理地址

用途

備注

…………

…………

?

101000h

Page tables(PTE)

?

100000h

PDT

頁(yè)目錄

F0000h

System ROM

?

E0000h

Expansion of sys ROM

?

C0000h

?

?

A0000h

?

?

9fc00h

系統(tǒng)保留

?

90000h

Loader.bin

Loader原文件

80000h

Kernel.bin

內(nèi)核原始文件

30000h

Kernel

整理后的內(nèi)核

7e00h

Free

?

7c00h

Boot sector

?

500h

Free

?

400h

ROM BIOS參數(shù)

?

0h

Int vectors

?

???????7接著Loader將控制權(quán)交給kernel,跳轉(zhuǎn)到內(nèi)核的起始地址0x30400h。注意雖然控制權(quán)現(xiàn)在已經(jīng)是內(nèi)核了,但是esp仍然指向Loader雖在的內(nèi)存中,同時(shí)GDT信息也在loader的內(nèi)存中,所以我們需要將esp指向kernel中的堆棧,并且將loader中的GDT復(fù)制到kernel中。

???????8內(nèi)核開始運(yùn)行,內(nèi)核的運(yùn)行情況見后文。

運(yùn)行到這里,看看可能的文件組織結(jié)構(gòu):

?

Tree:

|--Boot?????????

|--boot.asm????? //boot.bin

|--loader.asm???? // loader.bin

|--include

???????|--load.inc?

???????|--pm.inc?? //保護(hù)模式相關(guān)

???????|--fat12hdr.inc //文件系統(tǒng)相關(guān)

|--include

????????????? |--const.h?? ?

????????????? |--type.h?? //數(shù)據(jù)類型

????????????? |--protect.h

|--kernel

????????????? |--kernel.asm? //kernel.bin?其中包含內(nèi)核入口點(diǎn)_start和異常處理入口點(diǎn)。

????????????? |--start.c?????? //內(nèi)核的C入口cstart() / 初始化IDT

|--lib

????????????? |--string.asm?? //string

注意,在寫makefile的時(shí)候,至少要3個(gè)標(biāo)簽,分別為boot loader kernel 和 clean

?

???????9這時(shí),內(nèi)核已經(jīng)掌握了控制權(quán),但是由于沒(méi)有中斷,內(nèi)核幾乎不能做什么工作(不能進(jìn)程調(diào)度,不能接受輸入),所以接下來(lái)需要完成中斷處理。步驟為:

????????????? 1)設(shè)置和CPU直連的2個(gè)8259A芯片的寄存器,將硬件初始化(代碼位于starts.c中)。

????????????? 2)手動(dòng)建立IDT。

????????????? 3)建立異常處理,過(guò)程如下。

???????????????????? …………? //kernel.asm

divide_error:? //如果發(fā)生異常便會(huì)跳到此函數(shù)處運(yùn)行

?????? push 參數(shù)(包括錯(cuò)誤碼和錯(cuò)誤的ID)

call exception_hander //除零錯(cuò)處處理函數(shù),顯示錯(cuò)誤嗎

?

???????????????????? …………..//start.c中運(yùn)行

???????????????????? idt[INT_VECTOR_DEVIDE].selsect= GDT_idtseclet; //尋址時(shí)先在GDT中找到IDT的段地址在加上偏移找到devide_error()的線性地址

???????????????????? idt[INT_VECTOR_DEVIDE].offset= devide_erro r; //錯(cuò)誤處理函數(shù)為devide_error();? //idt中每一個(gè)元素代表了一個(gè)中斷向量,發(fā)生中斷時(shí)候,CPU會(huì)首先根據(jù)中斷寄存器找到idt的起始位置,然后根據(jù)中斷向量號(hào)和idt數(shù)組找到中斷處理程序的位置,并保存相關(guān)寄存器后跳轉(zhuǎn)到中斷處理程序處運(yùn)行!

?

????????????? 4)建立中斷處理(步驟和建立異常類似,就是中間多了一個(gè)設(shè)置初始化8259A)。

?

?

                                                          未完待續(xù)


總結(jié)

以上是生活随笔為你收集整理的一个操作系统的实现(1)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。