日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國內最全IT社區(qū)平臺 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當前位置:首頁 > 服務器 > 一個操作系統(tǒng)的實現(xiàn)(6)-初識分頁機制

一個操作系統(tǒng)的實現(xiàn)(6)-初識分頁機制

來源:程序員人生   發(fā)布時間:2016-06-03 13:18:15 閱讀次數(shù):2844次

這節(jié)依然是從實現(xiàn)的角度來說述分頁機制。

為何要引入分頁機制。我們都知道分段機制是為了提供保護機制,那末為何還要引入分頁機制呢?

為何引入分頁機制

想象1下這樣1種情況:假定我們用的計算機物理內存是4GB,但是我們的程序大小是5GB。那末這個時候我們沒法將程序全部放到內存中,也就沒法運行程序。分頁機制引入的緣由之1就是為了解決這個問題。分頁機制的引入實現(xiàn)了虛擬存儲器的機制。

另外,程序履行具有局部性,也就是說1段時間內,只需要程序代碼中的1小部份(相對全部程序)就能夠實現(xiàn)程序的履行。那末我們就不用把所有代碼和數(shù)據(jù)都寄存在內存中,而是將現(xiàn)在或很近的將來需要的代碼和數(shù)據(jù)放入內存就好了。要實現(xiàn)這個功能需要分頁機制。在這類情況下,相同大小的內存在引入分頁機制后可以同時寄存更多的程序。這由進1步提高了存儲器的容量。

在介紹分頁機制之前,首先我們需要了解3種地址:

邏輯地址、線性地址、物理地址

這3種地址的關系以下圖:

<font color=”red>這里是地址轉換圖:OS-adressAfterPagingAndSegment

引入段頁式存儲以后才有完全的3種地址的概念。這時候候邏輯地址通過分段機制轉換成線性地址,然后再通過分頁機制轉換成物理地址。

在沒有引入頁式存儲的情況下,邏輯地址通過分段機制轉換成的線性地址等于物理地址。

如果段式存儲和頁式存儲都不存在。那末也就不存在邏輯地址和線性地址,我們對內存的所有操作都直接使用物理地址。

通過上面的分析,我們很容易明白分頁機器就像1個函數(shù):

物理地址 = f(線性地址)

接下來,以2級頁表機制對分頁機制進行描寫

分頁機制概述

2級頁表的分頁機制以下圖:

上圖的轉換使用兩級頁表,第1級叫做頁目錄,大小為4KB,存儲在1個物理頁中,每一個表項4字節(jié)長,共有1024個表項。每一個表項對應第2級的1個頁表,第2級的每個頁表也有1024個表項,每個表項對應1個物理頁。頁目錄表的表項簡稱PDE(Page Directory Entry),頁表的表項簡稱PTE(Page Table Entry)。

進行轉換時,先是從由寄存器cr3指定的頁目錄中根據(jù)線性地址的高10位得到頁表地址,然后在頁表中根據(jù)線性地址的第12到21位得到物理頁首地址,將這個首地址加上線性地址低12位便得到了物理地址。

分頁機制是不是生效的開關位于cr0的最高位PG位。以下圖:

如果PG=1,則分頁機制生效。所以,當我們準備好了頁目錄表和頁表,并將cr3指向頁目錄表以后,只需要置PG位,分頁機制就開始工作了。

接下來描寫PDE和PTE的結構和各位的詳細解釋:

PDE和PTE

下圖是PDE的結構:

下圖是PTE的結構:

下面是關于PDE和PTE中各位的解釋:

  • P 存在位,表示當前條目所指向的頁或頁表是不是在物理內存中。P=0表示頁不在內存中,如果處理器試圖訪問此頁,將會產生頁異常(page-fault exception,#PF);P=1表示頁在內存中。

  • R / W 指定1個頁或1組頁(比如,此條目是指向頁表的頁目錄條目)的讀寫權限。此位與U/S位和寄存器cr0中的WP位相互作用。R/W=0表示只讀;R/W=1表示可讀并可寫。

  • U / S 指定1個頁或1組頁(比如,此條目是指向頁表的頁目錄條目)的特權級。此位與R/W位和寄存器cr0中的WP位相互作用。U/S=0表示系統(tǒng)級別(Supervisor Privilege Level),如果CPL為0、1或2,那末它便是在此級別;U/S=1表示用戶級別(User Privilege Level),如果CPL為3,那末它便是在此級別。
    如果cr0中的WP位為0,那末即使用戶級(User P.L.)頁面的R/W=0,系統(tǒng)級(Supervisor P.L.)程序依然具有寫權限;如果WP位為1,那末系統(tǒng)級(Supervisor P.L.)程序也不能寫入用戶級(User P.L.)只讀頁。

  • P W T 用于控制對單個頁或頁表的緩沖策略。PWT=0時使用Write-back緩沖策略;PWT=1時使用Write-through緩沖策略。當cr0寄存器的CD(Cache-Disable)位被設置時會被疏忽。

  • P C D 用于控制對單個頁或頁表的緩沖。PCD=0時頁或頁表可以被緩沖;PCD=1時頁或頁表不可以被緩沖。當cr0寄存器的CD(Cache-Disable)位被設置時會被疏忽。

  • A 唆使頁或頁表是不是被訪問。此位常常在頁或頁表剛剛被加載到物理內存中時被內存管理程序清零,處理器會在第1次訪問此頁或頁面時設置此位。而且,處理器其實不會自動清除此位,只有軟件能清除它。

  • D 唆使頁或頁表是不是被寫入。此位常常在頁或頁表剛剛被加載到物理內存中時被內存管理程序清零,處理器會在第1次寫入此頁或頁面時設置此位。而且,處理器其實不會自動清除此位,只有軟件能清除它。
    A位和D位都是被內存管理程序用來管理頁和頁表從物理內存中換入和換出的。

  • P S 決定頁大小。PS=0時頁大小為4KB,PDE指向頁表。

  • P A T 選擇PAT(Page Attribute Table)條目。Pentium III以后的CPU開始支持此位,在此不予討論,并在我們的程序中設為0。

  • G 唆使全局頁。如果此位被設置,同時cr4中的PGE位被置,那末此頁的頁表或頁目錄條目不會在TLB中變得無效,即使cr3被加載或任務切換時也是如此。

處理器會將最近經常使用的頁目錄和頁表項保存在1個叫做TLB(Translation Lookaside Buffer)的緩沖區(qū)中。只有在TLB中找不到被要求頁的轉換信息時,才會到內存中去尋覓。這樣就大大加快了訪問頁目錄和頁表的時間。

當頁目錄或頁表項被更改時,操作系統(tǒng)應當馬上使TLB中對應的條目無效,以便下次用到此條目時讓它取得更新。

當cr3被加載時,所有TLB都會自動無效,除非頁或頁表條目的G位被設置。

接下來看看cr3的結構:

cr3

cr3的結構以下圖:

cr3又叫做PDBR(Page-Directory Base Register)。它的高20位將是頁目錄表首地址的高20位,頁目錄表首地址的低12位會是零,也就是說,頁目錄表會是4KB對齊的。類似地,PDE中的頁表基址(PageTable Base Address)和PTE中的頁基址(PageBase Address)也是用高20位來表示4KB對齊的頁表和頁。

至于第3位和第4位的兩個標志,我們暫時可以疏忽它們。

cr0cr3PDEPTE的結構有了解以后,接下來編寫代碼啟動分頁機制:

編寫代碼啟動分頁機制

這里不斟酌特權級的變化,這樣更能專注于分頁機制的實現(xiàn)。

這里僅列出新增代碼,完全代碼會放在本文的最后。

8 PageDirBase equ 200000h ; 頁目錄開始地址: 2M 9 PageTblBase equ 201000h ; 頁表開始地址: 2M+4K ... 19 LABEL_DESC_PAGE_DIR: Descriptor PageDirBase, 4095, DA_DRW;Page Directory 20 LABEL_DESC_PAGE_TBL: Descriptor PageTblBase, 1023, DA_DRW|DA_LIMIT_4K;Page Tables ... 34 SelectorPageDir equ LABEL_DESC_PAGE_DIR - LABEL_GDT 35 SelectorPageTbl equ LABEL_DESC_PAGE_TBL - LABEL_GDT ... 166 [SECTION .s32]; 32 位代碼段. 由實模式跳入. 167 [BITS 32] 168 169 LABEL_SEG_CODE32: 170 call SetupPaging ... 202 ; 啟動分頁機制 -------------------------------------------------------------- 203 SetupPaging: 204 ; 為簡化處理, 所有線性地址對應相等的物理地址. 205 206 ; 首先初始化頁目錄 207 mov ax, SelectorPageDir ; 此段首地址為 PageDirBase 208 mov es, ax 209 mov ecx, 1024 ; 共 1K 個表項 210 xor edi, edi 211 xor eax, eax 212 mov eax, PageTblBase | PG_P | PG_USU | PG_RWW 213 .1: 214 stosd 215 add eax, 4096 ; 為了簡化, 所有頁表在內存中是連續(xù)的. 216 loop .1 217 218 ; 再初始化所有頁表 (1K 個, 4M 內存空間) 219 mov ax, SelectorPageTbl ; 此段首地址為 PageTblBase 220 mov es, ax 221 mov ecx, 1024 * 1024 ; 共 1M 個頁表項, 也即有 1M 個頁 222 xor edi, edi 223 xor eax, eax 224 mov eax, PG_P | PG_USU | PG_RWW 225 .2: 226 stosd 227 add eax, 4096 ; 每頁指向 4K 的空間 228 loop .2 229 230 mov eax, PageDirBase 231 mov cr3, eax 232 mov eax, cr0 233 or eax, 80000000h 234 mov cr0, eax 235 jmp short .3 236 .3: 237 nop 238 239 ret 240 ; 分頁機制啟動終了 ----------------------------------------------------------

上面的指令中,只有stosd沒有學過。類似的指令有stosbstoswstosd。這3個指令就是把alaxeax的內容存儲到edi指向的內存單元中,同時edi的值根據(jù)方向標志的值增加或減少。這里使用的是loop指令。它還可以同rep前綴聯(lián)合使用。這里我沒找到設置方向標志位的指令,難道是初始時候方向標志位已為0了?

上面的代碼實現(xiàn)的功能以下圖:

開頭的第207行和第208即將段寄存器es對應頁目錄表段,下面讓edi等于0,因而es:edi就指向了頁目錄表的開始。第214行的指令stosd第1次履行時就把eax中的PageTblBase|PG_P|PG_USU|PG_RWW存入了頁目錄表的第1個PDE。

那末來看看這個PDE是甚么值。PageTblBase|PG_P|PG_USU|PG_RWW(第212行)讓當前(第1個)PDE對應的頁表首地址變成PageTblBase,而且屬性顯示其指向的是存在的可讀可寫的用戶級別頁表。

實際上,當為頁目錄表中的第1個PDE賦值時,1個循環(huán)就已開始了。循環(huán)的每次履行中,es:edi會自動指向下1個PDE,而第215行也將下1個頁表的首地址增加4096字節(jié),以便與上1個頁表首尾相接。這樣,經過1024次循環(huán)(第209行由ecx指定)以后,頁目錄表中的所有PDE都被賦值終了,它們的屬性相同,都為指向可讀可寫的用戶級別頁表,并且所有的頁表連續(xù)排列在以
PageTblBase為首地址的4MB(4096×1024)的空間中。

接下來的工作是初始化所有頁表中的PTE(第218行到第228行)。由于總共有1024×1024個PTE,因而將ecx賦值為1024×1024,以便讓循環(huán)進行1024×1024次。開始對es和edi的處理讓es:edi指向了頁表段的首地址,即地址PageTblBase處,也是第1個頁表的首地址。

第1個頁表中的第1個PTE被賦值為PG_P|PG_USU|PG_RWW,不難理解,它表示此PTE唆使的頁首地址為0,并且是個可讀可寫的用戶級別頁。這同時意味著第0個頁表中第0個PTE唆使的頁的首地址是0,因而線性地址0~0FFFh將被映照到物理地址0~0FFFh,即f(x)=x,其中0x0FFFh。接下來進行的循環(huán)初始化了剩下的所有頁表中的PTE,將4GB空間的線性地址映照到相同的物理地址。如上圖所示

這樣,頁目錄表和所有的頁表被初始化終了。接下來到了正式啟動分頁機制的時候了。首先讓cr3指向頁目錄表(第230行和第231行),然后設置cr0的PG(第232行到第234行),這樣,分頁機制就啟動完成了。

運行結果以下:

從這里我們看到啟動分頁機制后。我們沒法在屏幕上看到分頁機制的影子。這是由于我們只是把所有的線性地址映照到完全相同的物理地址上,而并沒有對其做其他的操作。所以我們看不出來表面上的變化。而且這類方式會出現(xiàn)兩個問題:1是頁表明顯浪費得太多了,我們可能根本沒有那末大的內存;2是我們除“實現(xiàn)了”分頁,并沒有“得益于”分頁,也就是說,我們還沒有體會到分頁的妙處。上面的問題我們在下節(jié)介紹。

源代碼

; ========================================== ; pmtest6.asm ; 編譯方法:nasm pmtest6.asm -o pmtest6.com ; ========================================== %include "pm.inc" ; 常量, 宏, 和1些說明 PageDirBase equ 200000h ; 頁目錄開始地址: 2M PageTblBase equ 201000h ; 頁表開始地址: 2M+4K org 0100h jmp LABEL_BEGIN [SECTION .gdt] ; GDT ; 段基址, 段界限, 屬性 LABEL_GDT: Descriptor 0, 0, 0 ; 空描寫符 LABEL_DESC_NORMAL: Descriptor 0, 0ffffh, DA_DRW ; Normal 描寫符 LABEL_DESC_PAGE_DIR: Descriptor PageDirBase, 4095, DA_DRW;Page Directory LABEL_DESC_PAGE_TBL: Descriptor PageTblBase, 1023, DA_DRW|DA_LIMIT_4K;Page Tables LABEL_DESC_CODE32: Descriptor 0, SegCode32Len⑴, DA_C+DA_32 ; 非1致代碼段, 32 LABEL_DESC_CODE16: Descriptor 0, 0ffffh, DA_C ; 非1致代碼段, 16 LABEL_DESC_DATA: Descriptor 0, DataLen⑴, DA_DRW ; Data LABEL_DESC_STACK: Descriptor 0, TopOfStack, DA_DRWA + DA_32 ; Stack, 32 位 LABEL_DESC_VIDEO: Descriptor 0B8000h, 0ffffh, DA_DRW ; 顯存首地址 ; GDT 結束 GdtLen equ $ - LABEL_GDT ; GDT長度 GdtPtr dw GdtLen - 1 ; GDT界限 dd 0 ; GDT基地址 ; GDT 選擇子 SelectorNormal equ LABEL_DESC_NORMAL - LABEL_GDT SelectorPageDir equ LABEL_DESC_PAGE_DIR - LABEL_GDT SelectorPageTbl equ LABEL_DESC_PAGE_TBL - LABEL_GDT SelectorCode32 equ LABEL_DESC_CODE32 - LABEL_GDT SelectorCode16 equ LABEL_DESC_CODE16 - LABEL_GDT SelectorData equ LABEL_DESC_DATA - LABEL_GDT SelectorStack equ LABEL_DESC_STACK - LABEL_GDT SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT ; END of [SECTION .gdt] [SECTION .data1] ; 數(shù)據(jù)段 ALIGN 32 [BITS 32] LABEL_DATA: SPValueInRealMode dw 0 ; 字符串 PMMessage: db "In Protect Mode now. ^-^", 0 ; 進入保護模式后顯示此字符串 OffsetPMMessage equ PMMessage - $$ DataLen equ $ - LABEL_DATA ; END of [SECTION .data1] ; 全局堆棧段 [SECTION .gs] ALIGN 32 [BITS 32] LABEL_STACK: times 512 db 0 TopOfStack equ $ - LABEL_STACK - 1 ; END of [SECTION .gs] [SECTION .s16] [BITS 16] LABEL_BEGIN: mov ax, cs mov ds, ax mov es, ax mov ss, ax mov sp, 0100h mov [LABEL_GO_BACK_TO_REAL+3], ax mov [SPValueInRealMode], sp ; 初始化 16 位代碼段描寫符 mov ax, cs movzx eax, ax shl eax, 4 add eax, LABEL_SEG_CODE16 mov word [LABEL_DESC_CODE16 + 2], ax shr eax, 16 mov byte [LABEL_DESC_CODE16 + 4], al mov byte [LABEL_DESC_CODE16 + 7], ah ; 初始化 32 位代碼段描寫符 xor eax, eax mov ax, cs shl eax, 4 add eax, LABEL_SEG_CODE32 mov word [LABEL_DESC_CODE32 + 2], ax shr eax, 16 mov byte [LABEL_DESC_CODE32 + 4], al mov byte [LABEL_DESC_CODE32 + 7], ah ; 初始化數(shù)據(jù)段描寫符 xor eax, eax mov ax, ds shl eax, 4 add eax, LABEL_DATA mov word [LABEL_DESC_DATA + 2], ax shr eax, 16 mov byte [LABEL_DESC_DATA + 4], al mov byte [LABEL_DESC_DATA + 7], ah ; 初始化堆棧段描寫符 xor eax, eax mov ax, ds shl eax, 4 add eax, LABEL_STACK mov word [LABEL_DESC_STACK + 2], ax shr eax, 16 mov byte [LABEL_DESC_STACK + 4], al mov byte [LABEL_DESC_STACK + 7], ah ; 為加載 GDTR 作準備 xor eax, eax mov ax, ds shl eax, 4 add eax, LABEL_GDT ; eax <- gdt 基地址 mov dword [GdtPtr + 2], eax ; [GdtPtr + 2] <- gdt 基地址 ; 加載 GDTR lgdt [GdtPtr] ; 關中斷 cli ; 打開地址線A20 in al, 92h or al, 00000010b out 92h, al ; 準備切換到保護模式 mov eax, cr0 or eax, 1 mov cr0, eax ; 真正進入保護模式 jmp dword SelectorCode32:0 ; 履行這1句會把 SelectorCode32 裝入 cs, 并跳轉到 Code32Selector:0 處 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; LABEL_REAL_ENTRY: ; 從保護模式跳回到實模式就到了這里 mov ax, cs mov ds, ax mov es, ax mov ss, ax mov sp, [SPValueInRealMode] in al, 92h ; ┓ and al, 11111101b ; ┣ 關閉 A20 地址線 out 92h, al ; ┛ sti ; 開中斷 mov ax, 4c00h ; ┓ int 21h ; ┛回到 DOS ; END of [SECTION .s16] [SECTION .s32]; 32 位代碼段. 由實模式跳入. [BITS 32] LABEL_SEG_CODE32: call SetupPaging mov ax, SelectorData mov ds, ax ; 數(shù)據(jù)段選擇子 mov ax, SelectorVideo mov gs, ax ; 視頻段選擇子 mov ax, SelectorStack mov ss, ax ; 堆棧段選擇子 mov esp, TopOfStack ; 下面顯示1個字符串 mov ah, 0Ch ; 0000: 黑底 1100: 紅字 xor esi, esi xor edi, edi mov esi, OffsetPMMessage ; 源數(shù)據(jù)偏移 mov edi, (80 * 10 + 0) * 2 ; 目的數(shù)據(jù)偏移。屏幕第 10 行, 第 0 列。 cld .1: lodsb test al, al jz .2 mov [gs:edi], ax add edi, 2 jmp .1 .2: ; 顯示終了 ; 到此停止 jmp SelectorCode16:0 ; 啟動分頁機制 -------------------------------------------------------------- SetupPaging: ; 為簡化處理, 所有線性地址對應相等的物理地址. ; 首先初始化頁目錄 mov ax, SelectorPageDir ; 此段首地址為 PageDirBase mov es, ax mov ecx, 1024 ; 共 1K 個表項 xor edi, edi xor eax, eax mov eax, PageTblBase | PG_P | PG_USU | PG_RWW .1: stosd add eax, 4096 ; 為了簡化, 所有頁表在內存中是連續(xù)的. loop .1 ; 再初始化所有頁表 (1K 個, 4M 內存空間) mov ax, SelectorPageTbl ; 此段首地址為 PageTblBase mov es, ax mov ecx, 1024 * 1024 ; 共 1M 個頁表項, 也即有 1M 個頁 xor edi, edi xor eax, eax mov eax, PG_P | PG_USU | PG_RWW .2: stosd add eax, 4096 ; 每頁指向 4K 的空間 loop .2 mov eax, PageDirBase mov cr3, eax mov eax, cr0 or eax, 80000000h mov cr0, eax jmp short .3 .3: nop ret ; 分頁機制啟動終了 ---------------------------------------------------------- SegCode32Len equ $ - LABEL_SEG_CODE32 ; END of [SECTION .s32] ; 16 位代碼段. 由 32 位代碼段跳入, 跳出后到實模式 [SECTION .s16code] ALIGN 32 [BITS 16] LABEL_SEG_CODE16: ; 跳回實模式: mov ax, SelectorNormal mov ds, ax mov es, ax mov fs, ax mov gs, ax mov ss, ax mov eax, cr0 and eax, 7FFFFFFEh ; PE=0, PG=0 mov cr0, eax LABEL_GO_BACK_TO_REAL: jmp 0:LABEL_REAL_ENTRY ; 段地址會在程序開始處被設置成正確的值 Code16Len equ $ - LABEL_SEG_CODE16 ; END of [SECTION .s16code]
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 亚洲一区二区日本 | 精品视频在线观看 | 国产精品视频一二三四区 | 国产一区二区免费视频 | 国产一区二区三区亚洲 | 中文字幕91 | 午夜精品久久久久久久爽 | 日韩一区二区在线视频 | 国产一区免费在线观看 | 在线视频一区二区三区 | 亚洲福利片 | 在线一区二区三区做爰视频网站 | 免费在线成人av | 4色网| 午夜激情视频在线 | 成人福利在线 | 精品欧美一区二区三区久久久 | 国产 一区 | 国产精品xxx在线观看www | 激情av在线播放 | aa国产 | 精品久久久久久国产 | 色福利网 | 久久久久久久久久久久久9999 | 亚洲日本va中文字幕久久 | 亚洲国产日韩在线 | 久久亚洲美女 | 国产伦精品一区二区 | 自拍欧美日韩 | 91精品久久久久久久99蜜桃 | 亚洲一区二区高清 | 日本a v在线播放 | 久久xxx| 在线不卡免费视频 | 亚洲精品在线电影 | 免费在线成人 | 激情网综合 | 国产精品久久久久久久久久 | 欧洲国产一区 | 九九免费视频 | 污污视频免费网站 |