這節(jié)講一下操作系統(tǒng)的內(nèi)存,內(nèi)存是一個(gè)非常重要的知識(shí),還是需要大致了解一下的。
虛擬內(nèi)存
講虛擬內(nèi)存之前先了解一下單片機(jī),單片機(jī)是沒(méi)有操作系統(tǒng)的,所以每次寫完代碼,都需要借助工具把程序燒錄進(jìn)去,這樣程序才能跑起來(lái)。
另外,單片機(jī)的 CPU 是直接操作內(nèi)存的「物理地址」。
在這種情況下,單片機(jī)要想在內(nèi)存中同時(shí)運(yùn)行兩個(gè)程序是不可能的。如果第一個(gè)程序在 2000 的位置有值,第二個(gè)程序也在相同的位置寫入了值,將會(huì)擦掉第一個(gè)程序存放在相同位置上的所有內(nèi)容,導(dǎo)致第一個(gè)程序完全奔潰。
單片機(jī)關(guān)鍵的問(wèn)題是這兩個(gè)程序都引用了絕對(duì)物理地址,而這正是我們最需要避免的。
我們可以把進(jìn)程所使用的地址「隔離」開(kāi)來(lái),即讓操作系統(tǒng)為每個(gè)進(jìn)程分配獨(dú)立的一套「虛擬地址」,人人都有,大家自己玩自己的地址就行,互不干涉。但是有個(gè)前提每個(gè)進(jìn)程都不能訪問(wèn)物理地址,至于虛擬地址最終怎么落到物理內(nèi)存里,對(duì)進(jìn)程來(lái)說(shuō)是透明的,操作系統(tǒng)已經(jīng)把這些都安排的明明白白了。

操作系統(tǒng)會(huì)提供一種機(jī)制,將不同進(jìn)程的虛擬地址和不同內(nèi)存的物理地址映射起來(lái)。
如果程序要訪問(wèn)虛擬地址的時(shí)候,由操作系統(tǒng)轉(zhuǎn)換成不同的物理地址,這樣不同的進(jìn)程運(yùn)行的時(shí)候,寫入的是不同的物理地址,這樣就不會(huì)沖突了。
于是,這里就引出了兩種地址的概念:
- 我們程序所使用的內(nèi)存地址叫做
虛擬內(nèi)存地址(Virtual Memory Address) - 實(shí)際存在硬件里面的空間地址叫
物理內(nèi)存地址(Physical Memory Address)。
操作系統(tǒng)是如何管理虛擬地址與物理地址之間的關(guān)系?
主要有兩種方式,分別是
內(nèi)存分段和內(nèi)存分頁(yè),分段是比較早提出的,我們先來(lái)看看內(nèi)存分段
分段
進(jìn)程是由若干個(gè)邏輯分段組成的,如可由代碼段、數(shù)據(jù)段、BSS段、棧段、堆段組成。不同的段是有不同的屬性的,所以虛擬地址和物理地址也就使用 分段(Segmentation)的形式把這些段分離出來(lái)。
在段存儲(chǔ)中,進(jìn)程的內(nèi)存空間被分成若干段,每個(gè)段內(nèi)的地址空間是必須連續(xù)的,不可分割的內(nèi)存塊,但不同段之間的地址空間可以不連續(xù)的,不同段之間的地址空間可以分布在內(nèi)存中的不同位置,它們之間可以有空閑區(qū)域或其他進(jìn)程的段。

虛擬地址和物理地址之間是通過(guò)
段表來(lái)映射的,段表內(nèi)存在元素段號(hào)、段基地址和段界限(該段占用的最大地址)。
如果要訪問(wèn)段 3 中偏移量 500 的虛擬地址,我們根據(jù)段表映射出段 3 基地址 7000 + 偏移量 500 = 7500,7500就是需要訪問(wèn)的真是物理地址了。
如果要訪問(wèn)段 3 中偏移量 1200 的虛擬地址,我們根據(jù)段表映射出段 3 基地址 7000 + 偏移量 1200 = 8300,而段3段最大地址為7000 + 1000 = 8000,明顯8300地址越界了,此時(shí)系統(tǒng)會(huì)拋出異常。
存在的問(wèn)題
- 第一個(gè)就是
外部?jī)?nèi)存碎片的問(wèn)題。
雖然每個(gè)段內(nèi)的地址空間是連續(xù)的,但由于各個(gè)段之間的分布不一定連續(xù),當(dāng)多個(gè)進(jìn)程釋放不同段的內(nèi)存時(shí),可能會(huì)導(dǎo)致地址空間中出現(xiàn)分散的空閑區(qū)域,難以重組成大的連續(xù)內(nèi)存塊,從而浪費(fèi)了內(nèi)存。
比如a進(jìn)程中地址段的內(nèi)存地址為0-100,數(shù)據(jù)段為150-250,堆段為400-800,棧段為850-900,且a進(jìn)程此時(shí)釋放,則這4個(gè)段的內(nèi)存地址也同時(shí)釋放;如果此時(shí)新的進(jìn)程b的地址段內(nèi)存占用200,數(shù)據(jù)段占用200,堆段占用 600,棧段占用600;那么只有400-800段可存放b進(jìn)程的地址段或者是數(shù)據(jù)段,而b進(jìn)程的堆段和棧堆需要申請(qǐng)更大的連續(xù)內(nèi)存空間,進(jìn)而a進(jìn)程中0-100、150-250和850-900內(nèi)存段將不會(huì)被存儲(chǔ),也就出現(xiàn)了外部?jī)?nèi)存碎片化了。 - 第二個(gè)就是
內(nèi)存交換的效率低的問(wèn)題。
解決「外部?jī)?nèi)存碎片」的問(wèn)題就是內(nèi)存交換。內(nèi)存交換是將LRU最不長(zhǎng)使用的內(nèi)存置換到SWAP磁盤空間中,也就是設(shè)計(jì)到磁盤的讀寫IO,眾所周知讀寫IO的速度是很慢的。
如果內(nèi)存交換的時(shí)候,交換的是一個(gè)占內(nèi)存空間很大的程序,這樣整個(gè)機(jī)器都會(huì)顯得卡頓,這也就是為什么會(huì)出現(xiàn)內(nèi)存交換的效率低的問(wèn)題。
為了解決內(nèi)存分段的「外部?jī)?nèi)存碎片和內(nèi)存交換效率低」的問(wèn)題,就出現(xiàn)了內(nèi)存分頁(yè)。
分頁(yè)
分頁(yè)是把整個(gè)虛擬和物理內(nèi)存空間切成一段段固定尺寸的大小。這樣一個(gè)連續(xù)并且尺寸固定的內(nèi)存空間,我們叫頁(yè)(Page)。在 Linux 下,每一頁(yè)的大小為 4KB。
虛擬地址與物理地址之間通過(guò)頁(yè)表來(lái)映射,如下圖:

頁(yè)表是存儲(chǔ)在內(nèi)存里的,內(nèi)存管理單元 (MMU)就做將虛擬內(nèi)存地址轉(zhuǎn)換成物理地址的工作。
而當(dāng)進(jìn)程訪問(wèn)的虛擬地址在頁(yè)表中查不到時(shí),系統(tǒng)會(huì)產(chǎn)生一個(gè)缺頁(yè)異常,進(jìn)入系統(tǒng)內(nèi)核空間分配物理內(nèi)存、更新進(jìn)程頁(yè)表,最后再返回用戶空間,恢復(fù)進(jìn)程的運(yùn)行。
在分頁(yè)機(jī)制下,虛擬地址分為兩部分,頁(yè)號(hào)和頁(yè)內(nèi)偏移,而頁(yè)表也分為倆部分,虛擬頁(yè)號(hào)和物理頁(yè)號(hào),虛擬頁(yè)號(hào)作為頁(yè)表的索引,虛擬內(nèi)存通過(guò)虛擬頁(yè)號(hào)在頁(yè)表中找到對(duì)應(yīng)的物理頁(yè)號(hào),然后加上頁(yè)內(nèi)偏移即真實(shí)的物理地址,見(jiàn)下圖。

總結(jié)一下,對(duì)于一個(gè)內(nèi)存地址轉(zhuǎn)換,其實(shí)就是這樣三個(gè)步驟:
- 把虛擬內(nèi)存地址,切分成頁(yè)號(hào)和偏移量;
- 根據(jù)頁(yè)號(hào),從頁(yè)表里面,查詢對(duì)應(yīng)的物理頁(yè)號(hào);
- 直接拿物理頁(yè)號(hào),加上前面的偏移量,就得到了物理內(nèi)存地址。
解決分段的問(wèn)題
上面說(shuō)了分頁(yè)解決了分段存在的倆大問(wèn)題,即外部?jī)?nèi)存碎片化高和內(nèi)存交換效率低的問(wèn)題,那么來(lái)看看分頁(yè)是怎么解決這倆問(wèn)題的。
使用分頁(yè)的方式,其內(nèi)存空間都是預(yù)先劃分好的,且是緊密排列的,
仍然舉一個(gè)分頁(yè)多個(gè)進(jìn)程申請(qǐng)內(nèi)存的例子:比如有3個(gè)進(jìn)程a b c,a占用的內(nèi)存地址為0-100,b為101-200,c為201-300,如果b進(jìn)程釋放后101-200的內(nèi)存地址也同時(shí)釋放,那么此時(shí)如果來(lái)一個(gè)需要500內(nèi)存的進(jìn)程d時(shí),其實(shí)101-200的內(nèi)存地址是可以被d使用,d剩余的400內(nèi)存地址可以繼續(xù)使用301-700,也就是說(shuō)d進(jìn)程的內(nèi)存地址不是連續(xù)的,存儲(chǔ)在; 101-200和301-700倆個(gè)地方。也正是這種存儲(chǔ)方式,解決段存儲(chǔ)時(shí)的內(nèi)存碎片化的問(wèn)題了。
由于分段的方式要求段內(nèi)的內(nèi)存必須是連續(xù)的,而分頁(yè)的方式則不需要要求頁(yè)之前是連續(xù)的,正因?yàn)槭沁@個(gè)原因,所以分頁(yè)解決了分段的外部?jī)?nèi)存碎片化高的問(wèn)題。
在虛擬內(nèi)存或者物理內(nèi)存中每頁(yè)大小為4kb,而小于4kb也是按照一頁(yè)來(lái)存儲(chǔ),也就頁(yè)內(nèi)會(huì)出現(xiàn)內(nèi)存浪費(fèi)的情況,同理,頁(yè)表會(huì)導(dǎo)致頁(yè)內(nèi)內(nèi)存碎變化的問(wèn)題。
如果內(nèi)存空間不夠,操作系統(tǒng)會(huì)把其他正在運(yùn)行的進(jìn)程中的「最近沒(méi)被使用」的內(nèi)存頁(yè)面給釋放掉,也就是暫時(shí)寫在硬盤上,稱為換出(Swap Out)。一旦需要的時(shí)候,再加載進(jìn)來(lái),稱為換入(Swap In)。所以,一次性寫入磁盤的也只有少數(shù)的一個(gè)頁(yè)或者幾個(gè)頁(yè),不會(huì)花太多時(shí)間,內(nèi)存交換的效率就相對(duì)比較高。
本質(zhì)是分段的方式內(nèi)存交換時(shí)是按照段為維度進(jìn)行交換,段的內(nèi)存有大有小,而分頁(yè)的方式是按照頁(yè)為維度進(jìn)行交換,但是頁(yè)的大小是固定的。
舉個(gè)分段例子,比如系統(tǒng)中只有1個(gè)進(jìn)程,內(nèi)存段大小分別為100K,200K,300K,且此時(shí)已經(jīng)沒(méi)有了內(nèi)存空間,新的進(jìn)程申請(qǐng)內(nèi)存時(shí)需要進(jìn)行內(nèi)存交換。如果新的進(jìn)程的一個(gè)段占用內(nèi)存大小為8K,那么需要將內(nèi)存段100K的這個(gè)段進(jìn)行內(nèi)存交換。
在舉個(gè)分頁(yè)的例子,比如系統(tǒng)只有1個(gè)進(jìn)程,且內(nèi)存占用400K,也就是100頁(yè),此時(shí)系統(tǒng)也正好沒(méi)有內(nèi)存空間,新的進(jìn)程申請(qǐng)內(nèi)存時(shí)需要進(jìn)行內(nèi)存交換。如果新的進(jìn)程占用內(nèi)存大小為8K,那么只需要將這個(gè)100頁(yè)中取出倆頁(yè)「最近沒(méi)被使用」的頁(yè)即可,而不像分段中直接內(nèi)存交換100K。
很明顯的可以看出分頁(yè)的方式對(duì)于內(nèi)存交換時(shí)的效率明顯高于分段的方式。
自身存在的問(wèn)題
簡(jiǎn)單的分頁(yè)有什么缺陷嗎?
有空間上的缺陷。
因?yàn)椴僮飨到y(tǒng)是可以同時(shí)運(yùn)行非常多的進(jìn)程的,那這不就意味著頁(yè)表會(huì)非常的龐大。
在 32 位的環(huán)境下,虛擬地址空間共有 4GB,假設(shè)一個(gè)頁(yè)的大小是 4KB(2^12),那么就需要大約 100 萬(wàn) (2^20) 個(gè)頁(yè),每個(gè)「頁(yè)表項(xiàng)」需要 4 個(gè)字節(jié)大小來(lái)存儲(chǔ),那么整個(gè) 4GB 空間的映射就需要有 4MB 的內(nèi)存來(lái)存儲(chǔ)頁(yè)表。
這 4MB 大小的頁(yè)表,看起來(lái)也不是很大。但是要知道每個(gè)進(jìn)程都是有自己的虛擬地址空間的,也就說(shuō)都有自己的頁(yè)表。
那么,100 個(gè)進(jìn)程的話,就需要 400MB 的內(nèi)存來(lái)存儲(chǔ)頁(yè)表,這是非常大的內(nèi)存了,更別說(shuō) 64 位的環(huán)境了
多級(jí)頁(yè)表
要解決上面的問(wèn)題,就需要采用一種叫作多級(jí)頁(yè)表(Multi-Level Page Table)的解決方案。
在前面我們知道了,對(duì)于單頁(yè)表的實(shí)現(xiàn)方式,在 32 位和頁(yè)大小 4KB 的環(huán)境下,一個(gè)進(jìn)程的頁(yè)表需要裝下 100 多萬(wàn)個(gè)「頁(yè)表項(xiàng)」,并且每個(gè)頁(yè)表項(xiàng)是占用 4 字節(jié)大小的,于是相當(dāng)于每個(gè)頁(yè)表需占用 4MB 大小的空間。
我們把這個(gè) 100 多萬(wàn)個(gè)「頁(yè)表項(xiàng)」的單級(jí)頁(yè)表再分頁(yè),將頁(yè)表(一級(jí)頁(yè)表)分為 1024 個(gè)頁(yè)表(二級(jí)頁(yè)表),每個(gè)表(二級(jí)頁(yè)表)中包含1024 個(gè)「頁(yè)表項(xiàng)」,形成二級(jí)分頁(yè)。如下圖所示:

你可能會(huì)問(wèn),分了二級(jí)表,映射 4GB 地址空間就需要 4KB(一級(jí)頁(yè)表)+ 4MB(二級(jí)頁(yè)表)的內(nèi)存,這樣占用空間不是更大了嗎?
當(dāng)然如果 4GB 的虛擬地址全部都映射到了物理內(nèi)存上的話,二級(jí)分頁(yè)占用空間確實(shí)是更大了,但是,我們往往不會(huì)為一個(gè)進(jìn)程分配那么多內(nèi)存。
其實(shí)我們應(yīng)該換個(gè)角度來(lái)看問(wèn)題,還記得計(jì)算機(jī)組成原理里面無(wú)處不在的局部性原理么?
每個(gè)進(jìn)程都有 4GB 的虛擬地址空間,而顯然對(duì)于大多數(shù)程序來(lái)說(shuō),其使用到的空間遠(yuǎn)未達(dá)到 4GB,因?yàn)闀?huì)存在部分對(duì)應(yīng)的頁(yè)表項(xiàng)都是空的,根本沒(méi)有分配,對(duì)于已分配的頁(yè)表項(xiàng),如果存在最近一定時(shí)間未訪問(wèn)的頁(yè)表,在物理內(nèi)存緊張的情況下,操作系統(tǒng)會(huì)將頁(yè)面換出到硬盤,也就是說(shuō)不會(huì)占用物理內(nèi)存。
如果使用了二級(jí)分頁(yè),一級(jí)頁(yè)表就可以覆蓋整個(gè) 4GB 虛擬地址空間,但如果某個(gè)一級(jí)頁(yè)表的頁(yè)表項(xiàng)沒(méi)有被用到,也就不需要?jiǎng)?chuàng)建這個(gè)頁(yè)表項(xiàng)對(duì)應(yīng)的二級(jí)頁(yè)表了,即可以在需要時(shí)才創(chuàng)建二級(jí)頁(yè)表。做個(gè)簡(jiǎn)單的計(jì)算,假設(shè)只有 20% 的一級(jí)頁(yè)表項(xiàng)被用到了,那么頁(yè)表占用的內(nèi)存空間就只有 4KB(一級(jí)頁(yè)表) + 20% * 4MB(二級(jí)頁(yè)表)= 0.804MB,這對(duì)比單級(jí)頁(yè)表的 4MB 是不是一個(gè)巨大的節(jié)約?
那么為什么不分級(jí)的頁(yè)表就做不到這樣節(jié)約內(nèi)存呢?
我們從頁(yè)表的性質(zhì)來(lái)看,保存在內(nèi)存中的頁(yè)表承擔(dān)的職責(zé)是將虛擬地址翻譯成物理地址。假如虛擬地址在頁(yè)表中找不到對(duì)應(yīng)的頁(yè)表項(xiàng),計(jì)算機(jī)系統(tǒng)就不能工作了。所以頁(yè)表一定要覆蓋全部虛擬地址空間,不分級(jí)的頁(yè)表就需要有 100 多萬(wàn)個(gè)頁(yè)表項(xiàng)來(lái)映射,而二級(jí)分頁(yè)則只需要 1024 個(gè)頁(yè)表項(xiàng)(此時(shí)一級(jí)頁(yè)表覆蓋到了全部虛擬地址空間,二級(jí)頁(yè)表在需要時(shí)創(chuàng)建)。
我們把二級(jí)分頁(yè)再推廣到多級(jí)頁(yè)表,就會(huì)發(fā)現(xiàn)頁(yè)表占用的內(nèi)存空間更少了,這一切都要?dú)w功于對(duì)局部性原理的充分應(yīng)用。
對(duì)于 64 位的系統(tǒng),兩級(jí)分頁(yè)肯定不夠了,可以變成了四級(jí)目錄,或者更多級(jí)。
那么你知道多集頁(yè)表到底長(zhǎng)什么樣嗎?以及虛擬地址在多級(jí)頁(yè)表中尋找真實(shí)物理地址的過(guò)程嗎?可以看下面這個(gè)圖。

可以看出一級(jí)頁(yè)表第一列存儲(chǔ)的是范圍的虛擬頁(yè)號(hào),第二列是二級(jí)頁(yè)表的地址,二級(jí)頁(yè)表中第一列存儲(chǔ)的是所屬一級(jí)范圍內(nèi)的所有虛擬頁(yè)號(hào),第二列對(duì)應(yīng)的是真實(shí)的物理地址。
比如虛擬地址2028尋找真實(shí)物理地址的過(guò)程是怎么樣的呢?
- 先在一級(jí)頁(yè)表中尋找,發(fā)現(xiàn)所屬1024-2048范圍,屬于一級(jí)頁(yè)表第二項(xiàng),則獲取二級(jí)頁(yè)表地址為5454tggg
- 找到二級(jí)頁(yè)表后,則通過(guò)二級(jí)頁(yè)表的第一列尋找對(duì)應(yīng)的2028虛擬地址,找到后第二列即為真實(shí)的物理地址。
TLB
多級(jí)頁(yè)表雖然解決了空間上的問(wèn)題,但是虛擬地址到物理地址的轉(zhuǎn)換就多了幾道轉(zhuǎn)換的工序,這顯然就降低了這倆地址轉(zhuǎn)換的速度,也就是帶來(lái)了時(shí)間上的開(kāi)銷。
我們可以把最常訪問(wèn)的幾個(gè)頁(yè)表項(xiàng)存儲(chǔ)到訪問(wèn)速度更快的硬件,于是計(jì)算機(jī)科學(xué)家們,就在 CPU 芯片中,加入了一個(gè)專門存放程序最常訪問(wèn)的頁(yè)表項(xiàng)的 Cache,這個(gè) Cache 就是 TLB(Translation Lookaside Buffer) ,通常稱為頁(yè)表緩存、轉(zhuǎn)址旁路緩存、快表等。
有了 TLB 后,那么 CPU 在尋址時(shí),會(huì)先查 TLB,如果沒(méi)找到,才會(huì)繼續(xù)查常規(guī)的頁(yè)表。
TLB 的命中率其實(shí)是很高的,因?yàn)槌绦蜃畛TL問(wèn)的頁(yè)就那么幾個(gè)。
內(nèi)存交換
我們知道虛擬內(nèi)存可以實(shí)現(xiàn)運(yùn)行內(nèi)存大于物理內(nèi)存,那么具體是怎么實(shí)現(xiàn)的呢?
先仔細(xì)看看下面的描述。


比如64位系統(tǒng)下,物理內(nèi)存是4G,程序要申請(qǐng)8G的內(nèi)存,可以嗎?答案是可以的。
- 上面說(shuō)了,程序申請(qǐng)內(nèi)存時(shí)實(shí)際申請(qǐng)的虛擬內(nèi)存,那么64位系統(tǒng)每個(gè)進(jìn)程用戶空間的虛擬內(nèi)存128T,肯定是可以申請(qǐng)到8G內(nèi)存的。(32位系統(tǒng)用戶的虛擬空間是3G,是不可以申請(qǐng)到8G的)
- 在虛擬內(nèi)存和物理內(nèi)存建立頁(yè)表之后,并不是一次將8G的頁(yè)全部加在到物理內(nèi)存中,而在用到對(duì)應(yīng)的指令和數(shù)據(jù)時(shí),才會(huì)加在到物理內(nèi)存中。
- 基于2點(diǎn)中提到了(第二點(diǎn)很重要,不是一次性加載到物理內(nèi)存中,而是運(yùn)行哪里加載哪里到物理內(nèi)存),比如此時(shí)物理內(nèi)存中已經(jīng)加載程序的物理內(nèi)存為4G了,程序繼續(xù)運(yùn)行發(fā)現(xiàn)物理內(nèi)存不夠了,那么此時(shí)可以使用就內(nèi)存交換,將4G物理內(nèi)存中最久未使用的置換到磁盤中,騰出一部分物理內(nèi)存保證程序的可運(yùn)行。。。。就這樣循環(huán)內(nèi)存交換,最終可實(shí)現(xiàn)了運(yùn)行8G內(nèi)存的程序了。
總結(jié):第一點(diǎn):程序申請(qǐng)的是虛擬內(nèi)存,而不是物理內(nèi)存;第二點(diǎn):程序不是一次性加載到物理內(nèi)存中,而是運(yùn)行對(duì)應(yīng)的數(shù)據(jù)加載到內(nèi)存;第三點(diǎn):使用內(nèi)存交換技術(shù),實(shí)現(xiàn)運(yùn)行內(nèi)存大于物理內(nèi)存。
總結(jié)
虛擬內(nèi)存的作用大致下面3點(diǎn):
- 第一,虛擬內(nèi)存可以使得進(jìn)程對(duì)運(yùn)行內(nèi)存超過(guò)物理內(nèi)存大小,因?yàn)槌绦蜻\(yùn)行符合局部性原理,CPU 訪問(wèn)內(nèi)存會(huì)有很明顯的重復(fù)訪問(wèn)的傾向性,對(duì)于那些沒(méi)有被經(jīng)常使用到的內(nèi)存,我們可以把它換出到物理內(nèi)存之外,比如硬盤上的 swap 區(qū)域。
- 第二,由于每個(gè)進(jìn)程都有自己的頁(yè)表,所以每個(gè)進(jìn)程的虛擬內(nèi)存空間就是相互獨(dú)立的。進(jìn)程也沒(méi)有辦法訪問(wèn)其他進(jìn)程的頁(yè)表,所以這些頁(yè)表是私有的,這就解決了多進(jìn)程之間地址沖突的問(wèn)題。
- 第三,頁(yè)表里的頁(yè)表項(xiàng)中除了物理地址之外,還有一些標(biāo)記屬性的比特,比如控制一個(gè)頁(yè)的讀寫權(quán)限,標(biāo)記該頁(yè)是否存在等。在內(nèi)存訪問(wèn)方面,操作系統(tǒng)提供了更好的安全性。
在段存儲(chǔ)中,每個(gè)進(jìn)程的內(nèi)存被劃分為若干段,每一段都是連續(xù)的、不可分割的內(nèi)存塊。這意味著進(jìn)程在申請(qǐng)內(nèi)存時(shí),必須要找到足夠大的連續(xù)內(nèi)存塊,否則申請(qǐng)將失敗。這導(dǎo)致了外部碎片化問(wèn)題,因?yàn)獒尫诺膬?nèi)存塊可能會(huì)分散在地址空間中,難以重組成連續(xù)的內(nèi)存塊,從而浪費(fèi)了內(nèi)存。
在頁(yè)存儲(chǔ)中,內(nèi)存被劃分為固定大小的頁(yè)面,通常為4KB或其他大小。進(jìn)程申請(qǐng)的內(nèi)存可以跨越多個(gè)頁(yè)面,這些頁(yè)面可以在內(nèi)存中的不同位置,不需要連續(xù)。這種方式使得內(nèi)存管理更加靈活,減少了外部碎片化問(wèn)題,因?yàn)椴僮飨到y(tǒng)可以更容易地找到足夠的空閑頁(yè)面來(lái)滿足進(jìn)程的需求,而不需要考慮地址的連續(xù)性。