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

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

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

x86分页机制详解

發(fā)布時(shí)間:2025/3/15 编程问答 11 豆豆
生活随笔 收集整理的這篇文章主要介紹了 x86分页机制详解 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 1. 為什么會(huì)有分頁(yè)機(jī)制?
  • 2. 從虛擬地址到物理地址
  • 3. 簡(jiǎn)單的分頁(yè)模型
  • 4. 頁(yè)表和頁(yè)目錄
    • 4.1 層次化的分頁(yè)結(jié)構(gòu)
    • 4.2 頁(yè)表
    • 4.3 頁(yè)目錄
  • 5. 地址變換的具體過(guò)程

1. 為什么會(huì)有分頁(yè)機(jī)制?

有些資料說(shuō)是為了實(shí)現(xiàn)“虛擬內(nèi)存”,真的是這樣嗎?如果沒(méi)有分頁(yè)機(jī)制,能否實(shí)現(xiàn)“虛擬內(nèi)存”?答案是肯定的。

當(dāng)同時(shí)運(yùn)行的任務(wù)很多時(shí),內(nèi)存可能就不夠用。

如圖所示,每個(gè)段描述符都有 AVL 位(簡(jiǎn)稱 A 位),用于表示一個(gè)段最近是否被訪問(wèn)過(guò)(準(zhǔn)確地說(shuō)是表明從上次操作系統(tǒng)清零該位后一個(gè)段是否被訪問(wèn)過(guò))。

當(dāng)創(chuàng)建描述符的時(shí)候,應(yīng)該把 A 位清零。之后,每當(dāng)該段被訪問(wèn)時(shí),準(zhǔn)確地說(shuō)是處理器把這個(gè)段的段選擇符加載進(jìn)段寄存器時(shí),CPU 就將該位置“1”;對(duì)該位的清零是由操作系統(tǒng)負(fù)責(zé)的,通過(guò)定期監(jiān)視該位的狀態(tài),就可以統(tǒng)計(jì)出該段的使用頻率(比如,每 1 秒鐘查看一次,一旦置位就清零,統(tǒng)計(jì) 10 秒鐘內(nèi)被置位了多少次,次數(shù)越多說(shuō)明使用越頻繁)。當(dāng)內(nèi)存空間緊張時(shí),可以把不經(jīng)常使用的段退避到硬盤上,從而實(shí)現(xiàn)虛擬內(nèi)存管理。

當(dāng)某個(gè)段被換出到磁盤時(shí),操作系統(tǒng)應(yīng)該將這個(gè)段的描述符的 P 位清零。過(guò)上一段時(shí)間,當(dāng)再次訪問(wèn)這個(gè)段時(shí),因?yàn)樗拿枋龇?P 位是 0,處理器就會(huì)引發(fā)段不存在異常(中斷號(hào) 11)。這類中斷通常是由操作系統(tǒng)處理的,它會(huì)用同樣的方法騰出空間,然后把這個(gè)段從磁盤調(diào)入內(nèi)存。當(dāng)這類中斷返回時(shí),處理器會(huì)再次執(zhí)行引發(fā)異常的那條指令,這時(shí)候段已經(jīng)在內(nèi)存中(P=1),于是程序又可以繼續(xù)執(zhí)行了。

由此可見(jiàn),即使沒(méi)有分頁(yè)機(jī)制,利用“分段”也可以實(shí)現(xiàn)“虛擬內(nèi)存”。

但是,因?yàn)槎蔚拈L(zhǎng)度不固定,在段的換入換出時(shí)會(huì)產(chǎn)生外部碎片,這樣就浪費(fèi)了很多內(nèi)存。為了解決這個(gè)問(wèn)題,從 80386 處理器開始,引入了分頁(yè)機(jī)制。分頁(yè)機(jī)制簡(jiǎn)單來(lái)說(shuō),是用長(zhǎng)度固定的頁(yè)來(lái)代替長(zhǎng)度不定的段,以解決因段的長(zhǎng)度不同帶來(lái)的內(nèi)存空間管理變得復(fù)雜的問(wèn)題。

盡管操作系統(tǒng)也可以利用純軟件來(lái)實(shí)施固定長(zhǎng)度的內(nèi)存分配,但是過(guò)于復(fù)雜。由處理器固件來(lái)做這件事情,可以省去很多麻煩,速度也可以提高。

總結(jié)一下,引入分頁(yè)機(jī)制并不是為了實(shí)現(xiàn)虛擬內(nèi)存,而是為了解決內(nèi)存碎片的問(wèn)題。

2. 從虛擬地址到物理地址

分頁(yè)機(jī)制是 80x86 內(nèi)存管理機(jī)制的第二部分。分段機(jī)制把邏輯地址轉(zhuǎn)換成線性地址,而分頁(yè)機(jī)制則把線性地址轉(zhuǎn)換成物理地址。

分頁(yè)機(jī)制會(huì)把線性地址空間(段已映射到其中)劃分成頁(yè)面,然后這些線性地址空間的頁(yè)面被映射到物理地址空間的頁(yè)面上。如下圖所示:


80x86 使用 4K(2 的 12 次方)字節(jié)固定大小的頁(yè)面。每個(gè)頁(yè)面均是 4KB,且對(duì)齊于 4K 地址邊界處(地址的低 12 位全是 0)。

3. 簡(jiǎn)單的分頁(yè)模型

4GB(2 的 32 次方)的線性地址空間可以劃分為 1048576(= 2 的 20 次方,即 1M)個(gè)頁(yè)面。為了根據(jù)線性地址找到對(duì)應(yīng)的物理地址,操作系統(tǒng)必須維護(hù)一張表(如下圖所示)。


這個(gè)表暫且叫做“頁(yè)映射表”,它一共有 1048576 個(gè)表項(xiàng),每個(gè)表項(xiàng)占 4 個(gè)字節(jié),其內(nèi)容是某個(gè)頁(yè)的起始物理地址(共 32 比特,低 12 位全為 0)。

頁(yè)映射表是這樣使用的:因?yàn)轫?yè)的尺寸是 4KB,所以線性地址的低 12 位可以作為頁(yè)內(nèi)偏移,高 20 位可以用來(lái)索引一個(gè)表項(xiàng),找到了這個(gè)表項(xiàng),就找到了對(duì)應(yīng)的物理頁(yè)。

具體可以參考我的博文:簡(jiǎn)單的分頁(yè)模型

4. 頁(yè)表和頁(yè)目錄

4.1 層次化的分頁(yè)結(jié)構(gòu)

上文提到的頁(yè)映射表,一共有 1048576(=1M)個(gè)表項(xiàng),每個(gè)表項(xiàng)占 4 個(gè)字節(jié),所以表的大小是 4MB,在當(dāng)時(shí)看來(lái)要占用相當(dāng)一部分內(nèi)存??紤]到在實(shí)踐中,沒(méi)有哪個(gè)任務(wù)會(huì)真的用到所有表項(xiàng),充其量只是很小一部分,所以內(nèi)存中放一個(gè) 4MB 的表格確實(shí)很浪費(fèi)。也許你會(huì)建議,能不能先劃出一小片內(nèi)存,只存表格用到的部分,然后根據(jù)需要?jiǎng)討B(tài)擴(kuò)展。的確,這個(gè)方法可行。但是因?yàn)樘厥庠?#xff08;任務(wù)的 4GB 地址空間包括兩個(gè)部分:局部空間和全局空間。頁(yè)目錄的前半部分指向任務(wù)自己的頁(yè)表,后半部分則指向內(nèi)核的頁(yè)表。整個(gè)映射表的前一半對(duì)應(yīng)全局地址空間,后一半對(duì)應(yīng)局部地址空間),這張表從一開始就必須完全定義,所以不可避免地要占用 4MB 的內(nèi)存空間。為了解決這個(gè)問(wèn)題,同時(shí)又不會(huì)浪費(fèi)寶貴的內(nèi)存空間,處理器設(shè)計(jì)了層次化的分頁(yè)結(jié)構(gòu)。

4.2 頁(yè)表

4GB 的線性地址空間可以劃分為 1048576(2 的 20 次方,即 1M,也可以看成是 1024*1024)個(gè)頁(yè)面,所以,可以隨機(jī)地抽取這些頁(yè)面,每 1024 個(gè)頁(yè)面是一組,可以分成 1024 組。對(duì)于每組中 1024 個(gè)頁(yè)面的物理地址,按某種順序排列可以構(gòu)成一張表(每個(gè)表項(xiàng)都是一個(gè)頁(yè)面的物理地址),這個(gè)表就是頁(yè)表。頁(yè)表的大小是 1024*4B=4KB,剛好是一個(gè)物理頁(yè)的大小。

4.3 頁(yè)目錄

因?yàn)橐呀?jīng)分成了 1024 組,每組都有一個(gè)頁(yè)表(大小為 4KB),所以這 1024 個(gè)頁(yè)表又可以用一張表來(lái)指向,這就是頁(yè)目錄。類似于頁(yè)表,頁(yè)目錄共有 1024 個(gè)表項(xiàng)(稱作頁(yè)目錄項(xiàng)),**每個(gè)頁(yè)目錄項(xiàng)的內(nèi)容是某個(gè)頁(yè)表的物理地址。**頁(yè)表的大小是 1024*4B=4KB,剛好是一個(gè)物理頁(yè)的大小。

有人說(shuō),這樣不是更占內(nèi)存嗎?原來(lái)需要 4MB,現(xiàn)在存放 1024 個(gè)頁(yè)表就要 4MB,再加上一個(gè)頁(yè)目錄,還要 4KB,何苦呢?

  • 這樣的層次化分頁(yè)結(jié)構(gòu)是每個(gè)任務(wù)都有的,或者說(shuō)每個(gè)任務(wù)都有自己的頁(yè)目錄。在處理器內(nèi)部,有一個(gè)控制寄存器叫 CR3,存放著當(dāng)前任務(wù)的頁(yè)目錄的物理地址,故 CR3 又叫做頁(yè)目錄基址寄存器(Page Directory Base Register,PDBR).

  • 每個(gè)任務(wù)都有自己的 TSS(Task-State Segment ,任務(wù)狀態(tài)段),其中就包括了 CR3 寄存器域,存放著任務(wù)自己的頁(yè)目錄的物理地址。當(dāng)任務(wù)切換時(shí),CR3 寄存器的內(nèi)容也會(huì)被更新,更新為新任務(wù)的頁(yè)目錄的物理地址。

  • 頁(yè)目錄和頁(yè)表也是普通的頁(yè),混跡于全部的物理頁(yè)中。它們和普通的頁(yè)沒(méi)有什么區(qū)別,無(wú)非就是功能不一樣。當(dāng)任務(wù)被操作系統(tǒng)撤銷后,它們和任務(wù)所占用的普通的物理頁(yè)一樣會(huì)被回收。

  • 頁(yè)目錄總是在物理內(nèi)存中,頁(yè)表可以在需要時(shí)再分配,這樣就大大節(jié)省了物理內(nèi)存。這就回答了前面的問(wèn)題。

  • 5. 地址變換的具體過(guò)程

    具體怎么變換,還是用書上的例子來(lái)說(shuō)明吧。
    假設(shè)段部件輸出的線性地址是 0x00801050,如果沒(méi)有開啟分頁(yè),那么這個(gè)地址就是物理地址;但是現(xiàn)在開啟了分頁(yè),所以要經(jīng)過(guò)頁(yè)部件的轉(zhuǎn)換,才能得到物理地址。

    處理器的頁(yè)部件專門負(fù)責(zé)線性地址到物理地址的轉(zhuǎn)換工作。它首先將 32 位的線性地址分成 3 段,分別是高 10 位,中間 10 位和低 12 位。高 10 位用來(lái)索引頁(yè)目錄,中間 10 位用來(lái)索引頁(yè)表,低 12 位作為頁(yè)內(nèi)偏移。

  • 當(dāng)前任務(wù)的頁(yè)目錄的物理地址在 CR3 寄存器中,假設(shè)是 0x0000_5000;
  • 段部件輸出的線性地址是 0x0080_1050,按照高 10 位,中間 10 位和低 12 位分為三段,分別是0x002,0x001,0x050;
  • 0x002 乘以 4(因?yàn)槊總€(gè)表項(xiàng)占 4 個(gè)字節(jié))得到 0x008,作為偏移訪問(wèn)頁(yè)目錄,得到了0x0800_1000,這就是頁(yè)表的物理地址,順著它找到頁(yè)表;
  • 0x001 乘以 4(因?yàn)槊總€(gè)表項(xiàng)占 4 個(gè)字節(jié))得到 0x004,作為偏移訪問(wèn)頁(yè)表,得到了0x0000_c000,這就是我們要找的那個(gè)物理頁(yè)的起始地址。
  • 0x050 作為頁(yè)內(nèi)偏移,和物理頁(yè)的起始地址 0x0000_c000相加,得到 0x0000_c050,這就是最終的物理地址。

  • 參考資料
    【1】《x86匯編語(yǔ)言:從實(shí)模式到保護(hù)模式》(李忠,電子工業(yè)出版社)
    【2】《Linux內(nèi)核完全剖析》(趙炯,機(jī)械工業(yè)出版社,2006)

    總結(jié)

    以上是生活随笔為你收集整理的x86分页机制详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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