在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

從Intel CPU的發(fā)展歷史講起

程序員cxuan ? 來(lái)源:程序員cxuan ? 作者:程序員cxuan ? 2022-06-20 10:10 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

知乎上搜到一個(gè)比較有意思的話題:如何理解「進(jìn)入內(nèi)核態(tài)」,要回答好這個(gè)問(wèn)題需要對(duì)內(nèi)存管理及程序的運(yùn)行機(jī)制有比較深刻的了解,比如你需要了解內(nèi)存的分段,分頁(yè),中斷,特權(quán)級(jí)等機(jī)制,信息量比較大,本文將會(huì)從 Intel CPU 的發(fā)展歷史講起,循序漸近地幫助大家徹底掌握這一概念,相信大家看了肯定有幫助,本文目錄如下

CPU 運(yùn)行機(jī)制

Intel CPU 歷史發(fā)展史

分段

保護(hù)模式

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

系統(tǒng)調(diào)用

中斷

分段內(nèi)存的優(yōu)缺點(diǎn)

內(nèi)存分頁(yè)

總結(jié)

CPU 運(yùn)行機(jī)制

我們先簡(jiǎn)單地回顧一下 CPU 的工作機(jī)制,重新溫習(xí)一下一些基本概念,因?yàn)槲以诓殚嗁Y料的過(guò)程發(fā)現(xiàn)一些網(wǎng)友對(duì)尋址,CPU 是幾位的概念理解得有些模糊,理解了這些概念再去看 CPU 的發(fā)展史就不會(huì)再困惑。

CPU 是如何工作的呢?它是根據(jù)一條條的機(jī)器指令來(lái)執(zhí)行的,而機(jī)器指令= 操作碼+操作數(shù),操作數(shù)主要有三類:寄存器地址、內(nèi)存地址或立即數(shù)(即常量)。

我們所熟悉的程序就是一堆指令和數(shù)據(jù)的集合,當(dāng)打開(kāi)程序時(shí),裝載器把程序中的指令和數(shù)據(jù)加載到內(nèi)存中,然后由 CPU 進(jìn)行取指執(zhí)行指令。

在內(nèi)存中是以字節(jié)為基本單位來(lái)讀寫(xiě)數(shù)據(jù)的,我們可以把內(nèi)存看作是一個(gè)個(gè)的小格子(一般我們稱其為內(nèi)存單元),而每個(gè)小格子是一個(gè)字節(jié),那么對(duì)于 B8 0123H 這條指令來(lái)說(shuō),它在內(nèi)存中占三字節(jié),如下,CPU 該怎么找到這些格子呢,我們需要給這些格子編號(hào),這些編號(hào)也就是我們說(shuō)的內(nèi)存地址,根據(jù)內(nèi)存地址就是可以定位指令所在位置,從而取出里面的數(shù)據(jù)

19eaf55e-f02d-11ec-ba43-dac502259ad0.jpg

如圖示:內(nèi)存被分成了一個(gè)個(gè)的格子,每個(gè)格子一個(gè)字節(jié),20000~20002 分別為對(duì)應(yīng)格子的編號(hào)(即內(nèi)存地址)

CPU 執(zhí)行指令主要分為以下幾個(gè)步驟

取指令,CPU 怎么知道要去取哪條指令呢,它里面有一個(gè) IP 寄存器指向了對(duì)應(yīng)要取的指令的內(nèi)存地址, 然后這個(gè)內(nèi)存地址會(huì)通過(guò)地址總線找到對(duì)應(yīng)的格子,我們把這個(gè)過(guò)程稱為尋址,不難發(fā)現(xiàn)尋址能力決定于地址總線的位寬,假設(shè)地址總線位數(shù)為 20 位,那么內(nèi)存的可尋址空間為 2^20 * 1Byte = 1M,將格子(內(nèi)存單元)里面的數(shù)據(jù)(指令)取出來(lái)后,再通過(guò)數(shù)據(jù)總線發(fā)往 CPU 中的指令緩存區(qū)(指令寄存器),那么一次能傳多少數(shù)據(jù)呢,取決于數(shù)據(jù)總線的位寬,如果數(shù)據(jù)總線為 16 位,那么一次可以傳 16 bit 也就是兩個(gè)字節(jié)。

譯碼:指令緩沖區(qū)中的指令經(jīng)過(guò)譯碼以確定該進(jìn)行什么操作

執(zhí)行:譯碼后會(huì)由控制單元向運(yùn)算器發(fā)送控制指令進(jìn)行操作(比如執(zhí)行加減乘除等),執(zhí)行是由運(yùn)算器操縱數(shù)據(jù)也就是操作數(shù)進(jìn)行計(jì)算,而操作數(shù)保存在存儲(chǔ)單元(即片內(nèi)的緩存和寄存器組)中,由于操作數(shù)有可能是內(nèi)存地址,所以執(zhí)行中可能需要到內(nèi)存中獲取數(shù)據(jù)(這個(gè)過(guò)程稱為訪存),執(zhí)行后的結(jié)果保存在寄存器或?qū)懟貎?nèi)存中

1a02c49a-f02d-11ec-ba43-dac502259ad0.jpg

以指令 mov ax, 0123H 為例,它表示將數(shù)據(jù) 0123H 存到寄存器 AX 中,在此例中 AX 為 16 位寄存器,一次可以操作 16 位也就是 2 Byte 的數(shù)據(jù),所以我們將其稱為 16 位 CPU,CPU 是多少位取決于它一次執(zhí)行指令的數(shù)據(jù)帶寬,而數(shù)據(jù)帶寬又取決于通用寄存 器的位寬

更新 IP:執(zhí)行完一條指令后,更新 IP 中的值,將其指向下一條指令的起始地址,然后重復(fù)步驟 1

由以上總結(jié)可知尋址能力與寄存器位數(shù)有關(guān)。

接下來(lái)我們以執(zhí)行四條指令為例再來(lái)仔細(xì)看下 CPU 是如何執(zhí)行指令的,動(dòng)圖如下:

1a181868-f02d-11ec-ba43-dac502259ad0.gif

看到上面這個(gè)動(dòng)圖,細(xì)心地你可能會(huì)發(fā)現(xiàn)兩個(gè)問(wèn)題

前文說(shuō)指令地址是根據(jù) IP 來(lái)獲取的嗎,但上圖顯示指令地址卻是由「CS 左移四位 + IP」計(jì)算而來(lái)的,與我們所闡述的指令保存在 IP 寄存器中似乎有些出入,這是怎么回事呢?

動(dòng)圖顯示的地址是真實(shí)物理地址,這樣進(jìn)程之間可以互相訪問(wèn)/改寫(xiě)對(duì)方的物理地址,顯然是不安全的,那如何才能做到安全訪問(wèn)或者說(shuō)進(jìn)程間內(nèi)存的隔離呢

以上兩點(diǎn)其實(shí)只要我們了解一下 CPU 的發(fā)展歷史就明白解決方案了,有了以上的鋪墊,在明白了尋址,16/32/64 位 CPU等術(shù)語(yǔ)的含義后,再去了解 CPU 的發(fā)展故事會(huì)更容易得多,話不多說(shuō),發(fā)車

Intel CPU 歷史發(fā)展史

1971 年世界上第一塊 4 位 CPU-4004 微處理器橫空出世,1974 年 Intel 研發(fā)成功了 8 位 CPU-8080,這兩款 CPU 都是使用的絕對(duì)物理地址來(lái)尋址的,指令地址只存在于 IP 寄存器中(即只使用 IP 寄存器即可確定內(nèi)存地址)。由于是使用絕對(duì)物理地址尋址,也就意味著進(jìn)程之間的內(nèi)存數(shù)據(jù)可能會(huì)互相覆蓋,很不安全,所以這兩者只支持單進(jìn)程

分段

1978 年英特爾又研究成功了第一款 16 位 CPU - 8086,這款 CPU 可以說(shuō)是 x86 系列的鼻祖了,設(shè)計(jì)了 16 位的寄存器和 20 位的地址總線,所以內(nèi)存地址可以達(dá)到 2^20 Byte 即 1M,極大地?cái)U(kuò)展了地址空間,但是問(wèn)題來(lái)了,由于寄存器只有 16 位,那么 16 位的 IP 寄存器如何能尋址 20 位的地址呢,首先 Intel 工程師設(shè)計(jì)了一種分段的方法:1M 內(nèi)存可以分為 16 個(gè)大小為 64 K 的段,那么內(nèi)存地址就可以由「段的起始地址(也叫段基址) +段內(nèi)偏移(IP 寄存器中的值)」組成,對(duì)于進(jìn)程說(shuō)只需要關(guān)心 4 個(gè)段 ,代碼段,數(shù)據(jù)段,堆棧段,附加段,這幾個(gè)段的段基址分別保存在 CS,DS,SS,ES 這四個(gè)寄存器中

1a398c78-f02d-11ec-ba43-dac502259ad0.jpg

這四個(gè)寄存器也是 16 位,那怎么訪問(wèn) 20 位的內(nèi)存地址呢,實(shí)現(xiàn)也很簡(jiǎn)單,將每個(gè)寄存器的值左移四位,然后再加上段內(nèi)偏移即為尋址地址,CPU 都是取代碼段 中的指令來(lái)執(zhí)行的,我們以代碼段內(nèi)的尋址為例來(lái)計(jì)算內(nèi)存地址,指令的地址 = CS << 4 + IP ,這種方式做到了 20 位的尋址,只要改變 CS,IP 的值,即可實(shí)現(xiàn)在 0 到最大地址 0xFFFFF 全部 20 位地址的尋址

舉個(gè)例子:假設(shè) CS 存的數(shù)據(jù)為 0x2000,IP 為 0x0003,那么對(duì)應(yīng)的指令地址為

1a4eb4cc-f02d-11ec-ba43-dac502259ad0.jpg

圖示為真實(shí)的物理地址計(jì)算方式,從中可知, CS 其實(shí)保存的是真實(shí)物理地址的高 16 位

分段的初衷是為了解決尋址問(wèn)題,但本質(zhì)上段寄存器中保存的還是真實(shí)物理地址的段基礎(chǔ),且可以隨意指定,所以它也無(wú)法支持多進(jìn)程,因?yàn)檫@意味著進(jìn)程可以隨意修改 CS:IP 將其指向任意地址,很可能會(huì)覆蓋正在運(yùn)行的其他進(jìn)程的內(nèi)存,造成災(zāi)難性后果。

我們把這種使用真實(shí)物理地址且未加任何限制的尋址方式稱為實(shí)模式(real mode,即實(shí)際地址模式)

保護(hù)模式

實(shí)模式上的物理地址由段寄存器中的段基址:IP 計(jì)算而來(lái),而段基址可由用戶隨意指定,顯然非常不安全,于是 Intel 在之后推出了 80286 中啟用了保護(hù)模式,這個(gè)保護(hù)是怎么做的呢

首先段寄存器保存的不再是段基址了,而是段選擇子(Selector),其結(jié)構(gòu)如下

1a637a92-f02d-11ec-ba43-dac502259ad0.jpg

其中第 3 到 15 位保存的是描述符索引,此索引會(huì)根據(jù) TI 的值是 0 還是 1 來(lái)選擇是到 GDT(全局描述符表,一般也稱為段表)還是 LDT 來(lái)找段描述符,段描述符保存的是段基址和段長(zhǎng)度,找到段基址后再加上保存在 IP 寄存器中的段偏移量即為物理地址,段描述符的長(zhǎng)度統(tǒng)一為 8 個(gè)字節(jié),而 GDT/LDT 表的基地址保存在 gdtr/ldtr 寄存器中,以 GDT (此時(shí) TI 值為 0)為例來(lái)看看此時(shí) CPU 是如何尋址的

1a746442-f02d-11ec-ba43-dac502259ad0.jpg

可以看到程序中的地址是由段選擇子:段內(nèi)偏移量組成的,也叫邏輯地址,在只有分段內(nèi)存管理的情況下它也被稱為虛擬內(nèi)存

GDT 及段描述符的分配都是由操作系統(tǒng)管理的,進(jìn)程也無(wú)法更新 CS 等寄存器中值,這樣就避免了直接操作其他進(jìn)程以及自身的物理地址,達(dá)到了保護(hù)內(nèi)存的效果,從而為多進(jìn)程運(yùn)行提供了可能,我們把這種尋址方式稱為保護(hù)模式

那么保護(hù)模式是如何實(shí)現(xiàn)的呢,細(xì)心的你可能發(fā)現(xiàn)了上圖中在段選擇子和段描述符中里出現(xiàn)了RPL和DPL這兩個(gè)新名詞,這兩個(gè)表示啥意思呢?這就涉及到一個(gè)概念:特權(quán)級(jí)

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

我們知道 CPU 是根據(jù)機(jī)器指令來(lái)執(zhí)行的,但這些指令有些是非常危險(xiǎn)的,比如清內(nèi)存,置時(shí)鐘,分配系統(tǒng)資源等,這些指令顯然不能讓普通的進(jìn)程隨意執(zhí)行,應(yīng)該始終控制在操作系統(tǒng)中執(zhí)行,所以要把操作系統(tǒng)和普通的用戶進(jìn)程區(qū)分開(kāi)來(lái)

我們把一個(gè)進(jìn)程的虛擬地址劃分為兩個(gè)空間,用戶空間和內(nèi)核空間,用戶空間即普通進(jìn)程所處空間,內(nèi)核空間即操作系統(tǒng)所處空間

1a8c73e8-f02d-11ec-ba43-dac502259ad0.jpg

當(dāng) CPU 運(yùn)行于用戶空間(執(zhí)行用戶空間的指令)時(shí),它處于用戶態(tài),只能執(zhí)行普通的 CPU 指令 ,當(dāng) CPU 運(yùn)行于內(nèi)核空間(執(zhí)行內(nèi)核空間的指令)時(shí),它處于內(nèi)核態(tài),可以執(zhí)行清內(nèi)存,置時(shí)鐘,讀寫(xiě)文件等特權(quán)指令,那怎么區(qū)分 CPU 是在用戶態(tài)還是內(nèi)核態(tài)呢,CPU 定義了四個(gè)特權(quán)等級(jí),如下,從 0 到 3,特權(quán)等級(jí)依次遞減,當(dāng)特權(quán)級(jí)為 0 時(shí),CPU 處于內(nèi)核態(tài),可以執(zhí)行任何指令,當(dāng)特權(quán)級(jí)為 3 時(shí),CPU 處于用戶態(tài),在 Linux 中只用了 Ring 0,Ring 3 兩個(gè)特權(quán)等級(jí)

1a9acd3a-f02d-11ec-ba43-dac502259ad0.jpg

那么問(wèn)題來(lái)了,怎么知道 CPU 處于哪一個(gè)特權(quán)等級(jí)呢,還記得上文中我們提到的段選擇子嗎

1a637a92-f02d-11ec-ba43-dac502259ad0.jpg

其中的 RPL 表示請(qǐng)求特權(quán)((Requested privilege level))我們把當(dāng)前保存于 CS 段寄存器的段選擇子中的 RPL 稱為 CPL(current priviledge level),即當(dāng)前特權(quán)等級(jí),可以看到 RPL 有兩位,剛好對(duì)應(yīng)著 0,1,2,3 四個(gè)特權(quán)級(jí),而上文提到的 DPL 表示段描述符中的特權(quán)等級(jí)(Descriptor privilege level)知道了這兩個(gè)概念也就知道保護(hù)模式的實(shí)現(xiàn)原理了,CPU 會(huì)在兩個(gè)關(guān)鍵點(diǎn)上對(duì)內(nèi)存進(jìn)行保護(hù)

目標(biāo)段選擇子被加載時(shí)

當(dāng)通過(guò)線性地址(在只有段式內(nèi)存情況下,線性地址為物理地址)訪問(wèn)一個(gè)內(nèi)存頁(yè)時(shí)。由此可見(jiàn),保護(hù)也反映在內(nèi)存地址轉(zhuǎn)換的過(guò)程之中,既包括分段又包括分頁(yè)(后文分提到分頁(yè))

CPU 是怎么保護(hù)內(nèi)存的呢,它會(huì)對(duì) CPL,RPL,DPL 進(jìn)行如下檢查

1ab546b0-f02d-11ec-ba43-dac502259ad0.png

只有 CPL <= DPL 且 RPL <= DPL 時(shí),才會(huì)加載目標(biāo)代碼段執(zhí)行,否則會(huì)報(bào)一般保護(hù)異常 (General-protection exception)

那么特權(quán)等級(jí)(也就是 CPL)是怎么變化的呢,我們之前說(shuō)了 CPU 運(yùn)行于用戶空間時(shí),處于用戶態(tài),特權(quán)等級(jí)為 3,運(yùn)行于內(nèi)核空間時(shí),處于內(nèi)核態(tài),特權(quán)等級(jí)為 0,所以也可以換個(gè)問(wèn)法 CPU 是如何從用戶空間切換到內(nèi)核空間或者從內(nèi)核空間切換到用戶空間的,這就涉及到一個(gè)概念:系統(tǒng)調(diào)用

系統(tǒng)調(diào)用

我們知道用戶進(jìn)程雖然不能執(zhí)行特權(quán)指令,但有時(shí)候也需要執(zhí)行一些讀寫(xiě)文件,發(fā)送網(wǎng)絡(luò)包等操作,而這些操作又只能讓操作系統(tǒng)來(lái)執(zhí)行,那該怎么辦呢,可以讓操作系統(tǒng)提供接口,讓用戶進(jìn)程來(lái)調(diào)用即可,我們把這種方式叫做系統(tǒng)調(diào)用,系統(tǒng)調(diào)用可以直接由應(yīng)用程序調(diào)用,或者通過(guò)調(diào)用一些公用函數(shù)庫(kù)或 shell(這些函數(shù)庫(kù)或 shell 都封裝了系統(tǒng)調(diào)用接口)等也可以達(dá)到間接調(diào)用系統(tǒng)調(diào)用的目的。通過(guò)系統(tǒng)調(diào)用,應(yīng)用程序?qū)崿F(xiàn)了陷入(trap)內(nèi)核態(tài)的目的,這樣就從用戶態(tài)切換到了內(nèi)核態(tài)中,如下

1ac67502-f02d-11ec-ba43-dac502259ad0.jpg

應(yīng)用程序通過(guò)系統(tǒng)調(diào)用陷入內(nèi)核態(tài)

那么系統(tǒng)調(diào)用又是怎么實(shí)現(xiàn)的呢,主要是靠中斷實(shí)現(xiàn)的,接下來(lái)我們就來(lái)了解一下什么是中斷

中斷

陷入內(nèi)核態(tài)的系統(tǒng)調(diào)用主要是通過(guò)一種trap gate(陷阱門(mén))來(lái)實(shí)現(xiàn)的,它其實(shí)是軟件中斷的一種,由 CPU 主動(dòng)觸發(fā)給自己一個(gè)中斷向量號(hào),然后 CPU 根據(jù)此中斷向量號(hào)就可以去中斷向量表找到對(duì)應(yīng)的門(mén)描述符,門(mén)描述符與 GDT 中的段描述符相似,也是 8 個(gè)字節(jié),門(mén)描述符中包含段選擇子,段內(nèi)偏移,DPL 等字段 ,然后再根據(jù)段選擇子去 GDT(或者 LDT,下圖以 GDT 為例) 中查找對(duì)應(yīng)的段描述符,再找到段基地址,然后根據(jù)中斷描述符表的段內(nèi)偏移即可找到中斷處理例程的入口點(diǎn),整個(gè)中斷處理流程如下

1ae52574-f02d-11ec-ba43-dac502259ad0.jpg

畫(huà)外音:上圖中門(mén)描述符和段描述符只畫(huà)出了關(guān)鍵的幾個(gè)字段,省略了其它次要字段

當(dāng)然了,不是隨便發(fā)一個(gè)中斷向量都能被執(zhí)行,只有滿足一定條件的中斷才允許被普通的應(yīng)用程序調(diào)用,從發(fā)出軟件中斷再到執(zhí)行中斷對(duì)應(yīng)的代碼段會(huì)做如下的檢查

1af2e47a-f02d-11ec-ba43-dac502259ad0.jpg

一般應(yīng)用程序發(fā)出軟件中斷對(duì)應(yīng)的向量號(hào)是大家熟悉的 int 0x80(int 代表 interrupt),它的門(mén)描述符中的 DPL 為 3,所以能被所有的用戶程序調(diào)用,而它對(duì)應(yīng)的目標(biāo)代碼段描述符中的 DPL 為 0,所以當(dāng)通過(guò)中斷門(mén)檢查后(即 CPL <= 門(mén)描述符中的 DPL 成立),CPU 就會(huì)將 CS 寄存器中的 RPL(3) 替換為目標(biāo)代碼段描述符的 DPL(0),替換后的 CPL 也就變成了 0,通過(guò)這種方式完成了從用戶態(tài)到內(nèi)核態(tài)的替換,當(dāng)中斷代碼執(zhí)行后執(zhí)行 iret 指令又會(huì)切換回用戶態(tài)

另外當(dāng)執(zhí)行中斷程序時(shí),還需要首先把當(dāng)前用戶進(jìn)程中對(duì)應(yīng)的堆棧,返回地址等信息,以便切回到用戶態(tài)時(shí)能恢復(fù)現(xiàn)場(chǎng)

可以看到 int 80h 這種軟件中斷的執(zhí)行又是檢查特權(quán)級(jí),又是從用戶態(tài)切換到內(nèi)核態(tài),又是保存寄存器的值,可謂是非常的耗時(shí),光看一下以下圖示就知道像 int 0x80 這樣的軟件中斷開(kāi)銷是有多大了

1b03649e-f02d-11ec-ba43-dac502259ad0.png

系統(tǒng)調(diào)用

所以后來(lái)又開(kāi)發(fā)出了 SYSENTER/SYSCALL 這樣快速系統(tǒng)調(diào)用的指令,它們?nèi)∠藱?quán)限檢查,也不需要在中斷描述表(Interrupt Descriptor Table、IDT)中查找系統(tǒng)調(diào)用對(duì)應(yīng)的執(zhí)行過(guò)程,也不需要保存堆棧和返回地址等信息,而是直接進(jìn)入CPL 0,并將新值加載到與代碼和堆棧有關(guān)的寄存器當(dāng)中(cs,eip,ss 和 esp),所以極大地提升了性能

分段內(nèi)存的優(yōu)缺點(diǎn)

使用了保護(hù)模式后,程序員就可以在代碼中使用了段選擇子:段偏移量的方式來(lái)尋址,這不僅讓多進(jìn)程運(yùn)行成為了可能,而且也解放了程序員的生產(chǎn)力,我們完全可以認(rèn)為程序擁有所有的內(nèi)存空間(虛擬空間),因?yàn)槎芜x擇子是由操作系統(tǒng)分配的,只要操作系統(tǒng)保證不同進(jìn)程的段的虛擬空間映射到不同的物理空間上,不要重疊即可,也就是說(shuō)雖然各個(gè)程序的虛擬空間是一樣的,但由于它們映射的物理地址是不同且不重疊的,所以是能正常工作的,但是為了方便映射,一般要求在物理空間中分配的段是連續(xù)的(這樣只要維護(hù)映射關(guān)系的起始地址和對(duì)應(yīng)的空間大小即可)

1b262a06-f02d-11ec-ba43-dac502259ad0.jpg

段式內(nèi)存管理-虛擬空間與實(shí)際物理內(nèi)存的映射

但段式內(nèi)存管理缺點(diǎn)也很明顯:內(nèi)存碎片可能很大,舉個(gè)例子

1b3e3650-f02d-11ec-ba43-dac502259ad0.jpg

如上圖示,連續(xù)加載了三個(gè)程序到內(nèi)存中,如果把 Chrome 關(guān)閉了,此時(shí)內(nèi)存中有兩段 128 M的空閑內(nèi)存,但如果此時(shí)要加載一個(gè) 192 M 的程序 X 卻有心無(wú)力了 ,因?yàn)槎问絻?nèi)存需要?jiǎng)澐殖鲆粔K連續(xù)的內(nèi)存空間,此時(shí)你可以選擇把占 256 M 的 Python 程序先 swap 到磁盤(pán)中,然后緊跟著 512 M 內(nèi)存的后面劃分出 256 M 內(nèi)存,再給 Python 程序 swap 到這塊物理內(nèi)存中,這樣就騰出了連續(xù)的 256 M 內(nèi)存,從而可以加載程序 X 了,但這種頻繁地將幾十上百兆內(nèi)存與硬盤(pán)進(jìn)行 swap 顯然會(huì)對(duì)性能造成嚴(yán)重的影響,畢竟誰(shuí)都知道內(nèi)存和硬盤(pán)的讀寫(xiě)速度可是一個(gè)天上一個(gè)地上,如果一定要交換,能否每次 swap 得能少一點(diǎn),比如只有幾 K,這樣就能滿足我們的需求,分頁(yè)內(nèi)存管理就誕生了

內(nèi)存分頁(yè)

1985 年 intel 推出了 32 位處理器 80386,也是首款支持分頁(yè)內(nèi)存的 CPU

和分段這樣連續(xù)分配一整段的空間給程序相比,分頁(yè)是把整個(gè)物理空間切成一段段固定尺寸的大小,當(dāng)然為了映射,虛擬地址也需要切成一段段固定尺寸的大小,這種固定尺寸的大小我們一般稱其為頁(yè),在 LInux 中一般每頁(yè)的大小為 4KB,這樣虛擬地址和物理地址就通過(guò)頁(yè)來(lái)映射起來(lái)了

1b50854e-f02d-11ec-ba43-dac502259ad0.jpg

當(dāng)然了這種映射關(guān)系是需要一個(gè)映射表來(lái)記錄的,這樣才能把虛擬地址映射到物理內(nèi)存中,給定一個(gè)虛擬地址,它最終肯定在某個(gè)物理頁(yè)內(nèi),所以虛擬地址一般由「頁(yè)號(hào)+頁(yè)內(nèi)偏移」組成,而映射表項(xiàng)需要包含物理內(nèi)存的頁(yè)號(hào),這樣只要將頁(yè)號(hào)對(duì)應(yīng)起來(lái),再加上頁(yè)內(nèi)偏移,即可獲取最終的物理內(nèi)存

1b651018-f02d-11ec-ba43-dac502259ad0.jpg

于是問(wèn)題來(lái)了,映射表(也稱頁(yè)表)該怎么設(shè)計(jì)呢,我們以 32 位虛擬地址位置來(lái)看看,假設(shè)頁(yè)大小為 4K(2^12),那么至少需要 2^20 也就是 100 多萬(wàn)個(gè)頁(yè)表項(xiàng)才能完全覆蓋所有的虛擬地址,假設(shè)每一個(gè)頁(yè)表項(xiàng) 4 個(gè)字節(jié),那就意味著為一個(gè)進(jìn)程的虛擬地址就需要準(zhǔn)備 2^20 * 4 B = 4 M 的頁(yè)表大小,如果有 100 個(gè)進(jìn)程,就意味著光是頁(yè)表就要占用 400M 的空間了,這顯然是非常巨大的開(kāi)銷,那該怎么解決這個(gè)頁(yè)表空間占用巨大的問(wèn)題呢

我們注意到現(xiàn)在的做法是一次性為進(jìn)程分配了占用其所有虛擬空間的頁(yè)表項(xiàng),但實(shí)際上一個(gè)進(jìn)程根本用不到這么巨大的虛擬空間,所以這種分配方式無(wú)疑導(dǎo)致很多分配的頁(yè)表項(xiàng)白白浪費(fèi)了,那該怎么辦,答案是分級(jí)管理,等真正需要分配物理空間的時(shí)候再分配,其實(shí)大家可以想想我們熟悉的 windows 是怎么分配的,是不是一開(kāi)始只分配了 C 盤(pán),D盤(pán),E盤(pán),等要存儲(chǔ)的時(shí)候,先確定是哪個(gè)盤(pán),再在這個(gè)盤(pán)下分配目錄,然后再把文件存到這個(gè)目錄下,并不會(huì)一開(kāi)始就把所有盤(pán)的空間給分配完的

1b76c560-f02d-11ec-ba43-dac502259ad0.jpg

同樣的道理,以 32 位虛擬地址為例,我們也可以對(duì)頁(yè)表進(jìn)行分級(jí)管理, 頁(yè)表項(xiàng) 2^20 = 2^10 * 2^10 = 1024 * 1024,我們把一個(gè)頁(yè)表分成兩級(jí)頁(yè)表,第一級(jí)頁(yè)表 1024 項(xiàng),每一項(xiàng)都指向一個(gè)包含有 1024 個(gè)頁(yè)表項(xiàng)的二級(jí)頁(yè)表

1b849582-f02d-11ec-ba43-dac502259ad0.jpg

圖片來(lái)自《圖解系統(tǒng)》

這樣只有在一級(jí)頁(yè)表中的頁(yè)表項(xiàng)被分配的時(shí)候才會(huì)分配二級(jí)頁(yè)表,極大的節(jié)省了空間,我們簡(jiǎn)單算下,假設(shè) 4G 的虛擬空間進(jìn)程只用了 20%(已經(jīng)很大了,大部分用不到這么多),那么由于一級(jí)頁(yè)表空間為 1024 *4 = 4K,總的頁(yè)表空間為 4K+ 0.2 * 4M = 0.804M,相比于原來(lái)的 4M 是個(gè)巨大的提升!

那么對(duì)于分頁(yè)保護(hù)模式又是如何起作用的呢,同樣以 32 位為例,它的二級(jí)頁(yè)表項(xiàng)(也稱 page table entry)其實(shí)是以下結(jié)構(gòu)

1ba034fe-f02d-11ec-ba43-dac502259ad0.jpg

注意第三位(也就是 2 對(duì)應(yīng)的位置)有個(gè) U/S,它其實(shí)就是代表特權(quán)級(jí),表示的是用戶/超級(jí)用戶標(biāo)志。為 1 時(shí),允許所有特權(quán)級(jí)別的程序訪問(wèn);為 0 時(shí),僅允許特權(quán)級(jí)為0、1、2(Linux 中沒(méi)有 1,2)的程序(也就是內(nèi)核)訪問(wèn)。頁(yè)目錄中的這個(gè)位對(duì)其所映射的所有頁(yè)面起作用

既然分頁(yè)這么好,那么分段是不是可以去掉了呢,理論上確實(shí)可以,但 Intel 的 CPU 嚴(yán)格執(zhí)行了 backward compatibility(回溯兼容),也就是說(shuō)最新的 CPU 永遠(yuǎn)可以運(yùn)行針對(duì)早期 CPU 開(kāi)發(fā)的程序,否則早期的程序就得針對(duì)新 CPU 架構(gòu)重新開(kāi)發(fā)了(早期程序針對(duì)的是 CPU 的段式管理進(jìn)行開(kāi)發(fā)),這無(wú)論對(duì)用戶還是開(kāi)發(fā)者都是不能接受的(別忘了安騰死亡的一大原因就是由于不兼容之前版本的指令),兼容性雖然意味著每款新的 CPU 都得兼容老的指令,所背的歷史包袱越來(lái)越重,但對(duì)程序來(lái)說(shuō)能運(yùn)行肯定比重新開(kāi)發(fā)好,所以既然早期的 CPU 支持段,那么自從 80386 開(kāi)始的所有 CPU 也都得支持段,而分頁(yè)反而是可選的,也就意味著這些 CPU 的內(nèi)存管理都是段頁(yè)式管理,邏輯地址要先經(jīng)過(guò)段式管理單元轉(zhuǎn)成線性地址(也稱虛擬地址),然后再經(jīng)過(guò)頁(yè)式管理單元轉(zhuǎn)成物理內(nèi)存,如下

1bb5d7e6-f02d-11ec-ba43-dac502259ad0.jpg

分頁(yè)是可選項(xiàng)

在 Linux 中,雖然也是段頁(yè)式內(nèi)存管理,但它統(tǒng)一把 CS,DS,SS,ES 的段基址設(shè)置為了 0,段界限也設(shè)置為了整個(gè)虛擬內(nèi)存的長(zhǎng)度,所有段都分布在同一個(gè)地址空間,這種內(nèi)存模式也叫平坦內(nèi)存模型(flat memory model)

1bc5db64-f02d-11ec-ba43-dac502259ad0.png

平坦內(nèi)存模型

我們知道邏輯地址由段選擇子:段內(nèi)偏移地址組成,既然段選擇子指向的段基地址為 0,那也就意味著段內(nèi)偏移地址即為即為線性地址(也就是虛擬地址),由此可知 Linux 中所有程序的代碼都使用了虛擬地址,通過(guò)這種方式巧妙地繞開(kāi)了分段管理,分段只起到了訪問(wèn)控制和權(quán)限的作用(別忘了各種權(quán)限檢查依賴 DPL,RPL 等特權(quán)字段,特權(quán)極轉(zhuǎn)移也依賴于段選擇子中的 DPL 來(lái)切換的)

總結(jié)

看完本文相信大家對(duì)實(shí)模式,保護(hù)模式,特權(quán)級(jí)轉(zhuǎn)換,分段,分頁(yè)等概念應(yīng)該有了比較清晰的認(rèn)識(shí)。

我們簡(jiǎn)單總結(jié)一下,CPU 誕生之間,使用的絕對(duì)物理內(nèi)存來(lái)尋址(也就是實(shí)模式),隨后隨著 8086 的誕生,由于工藝的原因,雖然地址總線是 20 位,但寄存器卻只有 16 位,一個(gè)難題出現(xiàn)了,16 位的寄存器該怎么尋址 20 位的內(nèi)存地址呢,于是段的概念被提出了,段的出現(xiàn)雖然解決了尋址問(wèn)題,但本質(zhì)上 CS << 4 + IP 的尋址方式依然還是絕對(duì)物理地址,這樣的話由于地址會(huì)互相覆蓋,顯然無(wú)法做到多進(jìn)程運(yùn)行,于是保護(hù)模式被提出了,保護(hù)就是為了物理內(nèi)存免受非法訪問(wèn),于是用戶空間,內(nèi)核空間,特權(quán)級(jí)也被提出來(lái)了,段寄存器里保存的不再是段基址,而是段選擇子,由操作系統(tǒng)分配,用戶也無(wú)法隨意修改段選擇子,必須通過(guò)中斷的形式才能從用戶態(tài)陷入內(nèi)核態(tài),中斷執(zhí)行的過(guò)程也需要經(jīng)歷特權(quán)級(jí)的檢查,檢查通過(guò)之后特權(quán)級(jí)從 3 切換到了 0,于是就可以放心合法的執(zhí)行特權(quán)指令了??梢钥吹剑ㄟ^(guò)操作系統(tǒng)分配段選擇子+中斷的方式內(nèi)存得到了有效保護(hù),但是分段可能造成內(nèi)存碎片過(guò)大以致頻繁 swap 會(huì)影響性能的問(wèn)題,于是分頁(yè)出現(xiàn)了,保護(hù)模式+分頁(yè)終于可以讓多進(jìn)程,高效調(diào)度成為了可能

審核編輯 :李倩

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • cpu
    cpu
    +關(guān)注

    關(guān)注

    68

    文章

    11070

    瀏覽量

    216764
  • 程序
    +關(guān)注

    關(guān)注

    117

    文章

    3826

    瀏覽量

    82813
  • 數(shù)據(jù)總線
    +關(guān)注

    關(guān)注

    2

    文章

    62

    瀏覽量

    17891

原文標(biāo)題:非常硬核的解釋!

文章出處:【微信號(hào):cxuangoodjob,微信公眾號(hào):程序員cxuan】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    Intel-Altera FPGA:通信行業(yè)的加速引擎,開(kāi)啟高速互聯(lián)新時(shí)代

    Intel-Altera FPGA 是英特爾通過(guò)收購(gòu)Altera公司后獲得的可編程邏輯器件(FPGA)業(yè)務(wù),現(xiàn)以獨(dú)立子公司形式運(yùn)營(yíng),并由私募股權(quán)公司Silver Lake控股51%股權(quán)。一、歷史
    發(fā)表于 04-25 10:19

    CPU到GPU:渲染技術(shù)的演進(jìn)和趨勢(shì)

    渲染技術(shù)是計(jì)算機(jī)圖形學(xué)的核心內(nèi)容之一,它是將三維場(chǎng)景轉(zhuǎn)換為二維圖像的過(guò)程。渲染技術(shù)一直在不斷演進(jìn),最初的CPU渲染到后來(lái)的GPU渲染,性能和質(zhì)量都有了顯著提升。一、CPU到GPU:
    的頭像 發(fā)表于 02-21 11:11 ?719次閱讀
    <b class='flag-5'>從</b><b class='flag-5'>CPU</b>到GPU:渲染技術(shù)的演進(jìn)和趨勢(shì)

    聚焦離子束技術(shù)的歷史發(fā)展

    聚焦離子束(FIB)技術(shù)的演變與應(yīng)用聚焦離子束(FIB)技術(shù)已經(jīng)成為現(xiàn)代科技領(lǐng)域中不可或缺的一部分,尤其是在半導(dǎo)體制造和微納加工領(lǐng)域。盡管FIB技術(shù)已經(jīng)廣為人知,但其背后的歷史發(fā)展歷程卻鮮為人知
    的頭像 發(fā)表于 12-05 15:32 ?658次閱讀
    聚焦離子束技術(shù)的<b class='flag-5'>歷史</b><b class='flag-5'>發(fā)展</b>

    特斯拉看智能駕駛未來(lái)發(fā)展

    。特斯拉作為該領(lǐng)域的先行者,通過(guò)對(duì)算法、硬件、數(shù)據(jù)閉環(huán)和市場(chǎng)戰(zhàn)略的深度布局,為自動(dòng)駕駛行業(yè)的發(fā)展提供了重要借鑒。 ? 特斯拉智能駕駛歷史復(fù)盤(pán) 1.1 智能駕駛的起步:模塊化規(guī)則驅(qū)動(dòng)到端到端算法 特斯拉智能駕駛的技術(shù)進(jìn)化過(guò)程早在
    的頭像 發(fā)表于 11-16 16:49 ?1926次閱讀
    <b class='flag-5'>從</b>特斯拉看智能駕駛未來(lái)<b class='flag-5'>發(fā)展</b>

    霍爾傳感器的發(fā)展歷史與技術(shù)革新

    等多個(gè)領(lǐng)域的發(fā)展。本文將詳細(xì)探討霍爾傳感器的發(fā)展歷史,霍爾效應(yīng)的發(fā)現(xiàn)到其在現(xiàn)代科技中的廣泛應(yīng)用,揭示其背后的技術(shù)革新與產(chǎn)業(yè)變革。 霍爾效應(yīng)的發(fā)現(xiàn)與早期應(yīng)用 霍爾效應(yīng)的發(fā)現(xiàn)可以追溯到1
    的頭像 發(fā)表于 11-14 16:30 ?1129次閱讀

    手機(jī)芯片的歷史發(fā)展

    手機(jī)芯片的歷史和由來(lái)
    的頭像 發(fā)表于 09-20 08:50 ?7053次閱讀

    將軟件8位(字節(jié))可尋址CPU遷移至C28x CPU

    電子發(fā)燒友網(wǎng)站提供《將軟件8位(字節(jié))可尋址CPU遷移至C28x CPU.pdf》資料免費(fèi)下載
    發(fā)表于 09-06 10:42 ?0次下載
    將軟件<b class='flag-5'>從</b>8位(字節(jié))可尋址<b class='flag-5'>CPU</b>遷移至C28x <b class='flag-5'>CPU</b>

    簡(jiǎn)述微處理器的發(fā)展歷史

    微處理器的發(fā)展歷史是一部充滿創(chuàng)新與突破的技術(shù)演進(jìn)史,它見(jiàn)證了計(jì)算機(jī)技術(shù)的飛速發(fā)展和人類社會(huì)的巨大變革。以下是對(duì)微處理器發(fā)展歷史的詳細(xì)回顧,內(nèi)
    的頭像 發(fā)表于 08-22 14:22 ?5814次閱讀

    圖像處理器的發(fā)展歷史

    圖像處理器(Image Processor)的發(fā)展歷史是一段充滿創(chuàng)新與突破的歷程,它伴隨著計(jì)算機(jī)技術(shù)的不斷進(jìn)步和圖像處理需求的日益增長(zhǎng)而逐漸成熟。以下是對(duì)圖像處理器發(fā)展歷史的詳細(xì)回顧,
    的頭像 發(fā)表于 08-14 09:42 ?1956次閱讀

    射頻天線的發(fā)展歷史

    射頻天線,作為無(wú)線通信系統(tǒng)的關(guān)鍵組成部分,其發(fā)展歷程充滿了探索與創(chuàng)新。最初的簡(jiǎn)單形態(tài)到如今的復(fù)雜多樣,天線技術(shù)不僅見(jiàn)證了無(wú)線通信技術(shù)的飛速發(fā)展,也深刻影響了人類社會(huì)的方方面面。以下是對(duì)射頻天線
    的頭像 發(fā)表于 08-13 10:50 ?1807次閱讀

    簡(jiǎn)述光通信的發(fā)展歷史

    光通信的發(fā)展歷史是一段充滿創(chuàng)新與突破的旅程,它極大地推動(dòng)了現(xiàn)代通信技術(shù)的進(jìn)步,為人類社會(huì)帶來(lái)了前所未有的便捷與高效。以下是對(duì)光通信發(fā)展歷史的詳細(xì)介紹,分為幾個(gè)關(guān)鍵階段進(jìn)行闡述。
    的頭像 發(fā)表于 08-09 11:47 ?4202次閱讀

    risc-v的發(fā)展歷史

    RISC-V的發(fā)展歷史可以追溯到2006年左右,當(dāng)時(shí)David Patterson和其他研究者開(kāi)始探索創(chuàng)建一個(gè)開(kāi)放和可擴(kuò)展的指令集架構(gòu)(ISA)。以下是RISC-V發(fā)展的主要里程碑: 一、起源與初步
    發(fā)表于 07-29 17:20

    MEMS流量傳感器的發(fā)展歷史與原理

    來(lái)源:青島芯笙流量計(jì)和控制器 編輯:感知芯視界 Link 發(fā)展歷史 MEMS(Micro-Electro-Mechanical Systems,微電子機(jī)械系統(tǒng))流量傳感器的發(fā)展歷史可以
    的頭像 發(fā)表于 07-22 09:14 ?865次閱讀
    主站蜘蛛池模板: 国产又大又黄又粗又爽 | 免费一级欧美在线观看视频片 | 98色花堂永久地址国产精品 | 久久中文字幕一区二区 | 国产 麻豆 | 国产精品三区四区 | 夜夜操狠狠干 | 丁香六月婷婷精品免费观看 | 美女又黄又免费的视频 | 国外免费精品视频在线观看 | 韩国精品videosex性韩国 | 午夜影院免费入口 | 三级免费观看 | 免费黄视频在线观看 | 国产在线一卡 | 日韩一级在线观看 | 亚洲天堂ww | 天堂网站 | 天堂在线网 | 91大神精品视频 | 欧美不卡视频 | 欧美性猛交xxxx黑人猛交 | 在线播放视频网站 | 欧美区在线播放 | 午夜短视频| 精品久久久久国产免费 | 天天爽夜夜爽人人爽曰喷水 | 一本到卡二卡三卡视频 | 六月丁香深爱六月综合激情 | 国产狂喷冒白浆免费视频 | 圆胖肥女人性视频 | 综合色久七七综合七七蜜芽 | 狂野欧美激情性xxxx | 在线观看一区二区三区视频 | 2021国产精品午夜久久 | 天天干在线影院 | 午夜视频在线观看国产www | 黄网址免费 | 动漫精品成人免费网站 | 最近最新视频中文字幕4 | 综合激情网五月 |