|
1.Linux 進(jìn)程在內(nèi)存數(shù)據(jù)結(jié)構(gòu)
可以看到一個(gè)可執(zhí)行程序在存儲(chǔ)(沒(méi)有調(diào)入內(nèi)存)時(shí)分為代碼段,數(shù)據(jù)段,未初始化數(shù)據(jù)段三部分:
1) 代碼段:存放CPU執(zhí)行的機(jī)器指令。通常代碼區(qū)是共享的,即其它執(zhí)行程序可調(diào)用它。假如機(jī)器中有數(shù)個(gè)進(jìn)程運(yùn)行相同的一個(gè)程序,那么它們就可以使用同一個(gè)代碼段。 2) 數(shù)據(jù)段:存放已初始化的全局變量,靜態(tài)變量(包括全局和局部的),常量。static全局變量和static函數(shù)只能在當(dāng)前文件中被調(diào)用。 3) 未初始化數(shù)據(jù)區(qū)(uninitializeddata segment,BSS):存放全局未初始化的變量。BSS的數(shù)據(jù)在程序開始執(zhí)行之前被初始化為0或NULL。
代碼區(qū)所在的地址空間最低,往上依次是數(shù)據(jù)區(qū)和BSS區(qū),并且數(shù)據(jù)區(qū)和BSS區(qū)在內(nèi)存中是緊挨著的。。
可執(zhí)行程序在運(yùn)行時(shí)又多出了兩個(gè)區(qū)域:棧段(Stack)和堆段(Heap)。 4) 棧區(qū):由編譯器自動(dòng)釋放,存放函數(shù)的參數(shù)值,局部變量等。每當(dāng)一個(gè)函數(shù)被調(diào)用時(shí),該函數(shù)的返回類型和一些調(diào)用的信息被存儲(chǔ)到棧中。然后這個(gè)被調(diào)用的函數(shù)再為它的自動(dòng)變量和臨時(shí)變量在棧上分配空間。每調(diào)用一個(gè)函數(shù)一個(gè)新的棧就會(huì)被使用。棧區(qū)是從高地址位向低地址位增長(zhǎng)的,是一塊連續(xù)的內(nèi)在區(qū)域,最大容量是由系統(tǒng)預(yù)先定義好的,申請(qǐng)的??臻g超過(guò)這個(gè)界限時(shí)會(huì)提示溢出,用戶能從棧中獲取的空間較小。 5) 堆段:用于存放進(jìn)程運(yùn)行中被動(dòng)態(tài)分配的內(nèi)存段,位于BSS和棧中間的地址位。由程序員申請(qǐng)分配(malloc)和釋放(free)。堆是從低地址位向高地址位增長(zhǎng),采用鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)。頻繁地malloc/free造成內(nèi)存空間的不連續(xù),產(chǎn)生碎片。當(dāng)申請(qǐng)堆空間時(shí)庫(kù)函數(shù)按照一定的算法搜索可用的足夠大的空間。因此堆的效率比棧要低的多。
這個(gè)5中內(nèi)存區(qū)域中數(shù)據(jù)段、BSS和堆通常是被連續(xù)存儲(chǔ)的——內(nèi)存位置上是連續(xù)的,而代碼段和棧往往會(huì)被獨(dú)立存放。有趣的是堆和棧兩個(gè)區(qū)域關(guān)系很“曖昧”,他們一個(gè)向下“長(zhǎng)”(i386體系結(jié)構(gòu)中棧向下、堆向上),一個(gè)向上“長(zhǎng)”,相對(duì)而生。但你不必?fù)?dān)心他們會(huì)碰頭,因?yàn)樗麄冎g間隔很大(到底大到多少,你可以從下面的例子程序計(jì)算一下),絕少有機(jī)會(huì)能碰到一起。
下圖簡(jiǎn)要描述了進(jìn)程內(nèi)存區(qū)域的分布:

1. 物理地址(physical address)
物理內(nèi)存,真實(shí)存在的插在主板內(nèi)存槽上的內(nèi)存條的容量的大小.
內(nèi)存是由若干個(gè)存儲(chǔ)單元組成的,每個(gè)存儲(chǔ)單元有一個(gè)編號(hào),這種編號(hào)可唯一標(biāo)識(shí)一個(gè)存儲(chǔ)單元,稱為內(nèi)存地址(或物理地址)。我們可以把內(nèi)存看成一個(gè)從0字節(jié)一直到內(nèi)存最大容量逐字節(jié)編號(hào)的存儲(chǔ)單元數(shù)組,即每個(gè)存儲(chǔ)單元與內(nèi)存地址的編號(hào)相對(duì)應(yīng)。
2. 虛擬內(nèi)存(Virtual memory)(也叫虛擬存儲(chǔ)器)
虛擬內(nèi)存地址就是每個(gè)進(jìn)程可以直接尋址的地址空間,不受其他進(jìn)程干擾。每個(gè)指令或數(shù)據(jù)單元都在這個(gè)虛擬空間中擁有確定的地址。
虛擬內(nèi)存就是進(jìn)程中的目標(biāo)代碼,數(shù)據(jù)等虛擬地址組成的虛擬空間
虛擬內(nèi)存不考慮物理內(nèi)存的大小和信息存放的實(shí)際位置,只規(guī)定進(jìn)程中相互關(guān)聯(lián)信息的相對(duì)位置。每個(gè)進(jìn)程都擁有自己的虛擬內(nèi)存,且虛擬內(nèi)存的大小由處理機(jī)的地址結(jié)構(gòu)和尋址方式?jīng)Q定。
如直接尋址,如果cpu的有效地址長(zhǎng)度為16位,則其尋址范圍0 -64k。
再比如32位機(jī)器可以直接尋址4G空間,意思是每個(gè)應(yīng)用程序都有4G內(nèi)存空間可用。但是顯然機(jī)器內(nèi)存罕有如此之大,可以支持每個(gè)程序使用4G內(nèi)存的。 虛擬內(nèi)存與物理內(nèi)存的區(qū)別:虛擬內(nèi)存就與物理內(nèi)存相反,是指根據(jù)系統(tǒng)需要從硬盤虛擬地勻出來(lái)的內(nèi)存空間,是一種計(jì)算機(jī)系統(tǒng)內(nèi)存管理技術(shù),屬于計(jì)算機(jī)程序,而物理內(nèi)存為硬件。因?yàn)橛袝r(shí)候當(dāng)你處理大的程序時(shí)候系統(tǒng)內(nèi)存不夠用,此時(shí)就會(huì)把硬盤當(dāng)內(nèi)存來(lái)使用,來(lái)交換數(shù)據(jù)做緩存區(qū),不過(guò)物理內(nèi)存的處理速度是虛擬內(nèi)存的30倍以上。
3. 邏輯地址(logical address)
源程序經(jīng)過(guò)匯編或編譯后,形成目標(biāo)代碼,每個(gè)目標(biāo)代碼都是以0為基址順序進(jìn)行編址的,原來(lái)用符號(hào)名訪問(wèn)的單元用具體的數(shù)據(jù)——單元號(hào)取代。這樣生成的目標(biāo)程序占據(jù)一定的地址空間,稱為作業(yè)的邏輯地址空間,簡(jiǎn)稱邏輯空間。
在邏輯空間中每條指令的地址和指令中要訪問(wèn)的操作數(shù)地址統(tǒng)稱為邏輯地址。即應(yīng)用程序中使用的地址。要經(jīng)過(guò)尋址方式的計(jì)算或變換才得到內(nèi)存中的物理地址。
很簡(jiǎn)單,邏輯地址就是你源程序里使用的地址,或者源代碼經(jīng)過(guò)編譯以后編譯器將一些標(biāo)號(hào),變量轉(zhuǎn)換成的地址,或者相對(duì)于當(dāng)前段的偏移地址。
邏輯地址是指由程序產(chǎn)生的與段相關(guān)的偏移地址部分。例如,你在進(jìn)行C語(yǔ)言指針編程中,可以讀取指針變量本身值(&操作),實(shí)際上這個(gè)值就是邏輯地址,它是相對(duì)于你當(dāng)前進(jìn)程數(shù)據(jù)段的地址,不和絕對(duì)物理地址相干。只有在Intel實(shí)模式下,邏輯地址才和物理地址相等(因?yàn)閷?shí)模式?jīng)]有分段或分頁(yè)機(jī)制,Cpu不進(jìn)行自動(dòng)地址轉(zhuǎn)換);邏輯也就是在Intel保護(hù)模式下程序執(zhí)行代碼段限長(zhǎng)內(nèi)的偏移地址(假定代碼段、數(shù)據(jù)段如果完全一樣)。應(yīng)用程序員僅需與邏輯地址打交道,而分段和分頁(yè)機(jī)制對(duì)您來(lái)說(shuō)是完全透明的,僅由系統(tǒng)編程人員涉及。應(yīng)用程序員雖然自己可以直接操作內(nèi)存,那也只能在操作系統(tǒng)給你分配的內(nèi)存段操作。
不過(guò)有些資料是直接把邏輯地址當(dāng)成虛擬地址,兩者并沒(méi)有明確的界限。
在linux內(nèi)核,虛擬地址是3G-4G這段地址,它與物理地址通過(guò)頁(yè)表來(lái)映射,邏輯地址是指3G-3G+main_memory_size這段虛擬地址,它與物理地址的映射是線性的,當(dāng)然也可以通過(guò)頁(yè)表映射。所以邏輯地址是虛擬地址的一部分。
邏輯地址的組成:是由一個(gè)段標(biāo)識(shí)符加上一個(gè)指定段內(nèi)相對(duì)地址的偏移量,表示為 [段標(biāo)識(shí)符:段內(nèi)偏移量]

圖4.1 作業(yè)的名空間、邏輯地址空間和裝入后的物理空間
4. 線性地址或Linux下也叫虛擬地址(virtual address)
這個(gè)地址很重要,也很不容易理解。分段機(jī)制下CPU尋址是二維的地址即,段地址:偏移地址,CPU不可能認(rèn)識(shí)二維地址,因此需要轉(zhuǎn)化成一維地址即,段地址*16+偏移地址,這樣得到的地址便是線性地址(在未開啟分頁(yè)機(jī)制的情況下也是物理地址)。這樣有什么意義呢?或者說(shuō)這個(gè)一維地址的計(jì)算方法隨便一個(gè)學(xué)計(jì)算機(jī)的人都知道,但是你真的理解它的意思嗎?要想理解它的意思,必須要知道什么是地址空間,下文詳述。
線性地址是邏輯地址到物理地址變換之間的中間層。程序代碼會(huì)產(chǎn)生邏輯地址,或者說(shuō)是段中的偏移地址,加上相應(yīng)段的基地址就生成了一個(gè)線性地址。如果啟用了分頁(yè)機(jī)制,那么線性地址可以再經(jīng)變換以產(chǎn)生一個(gè)物理地址。若沒(méi)有啟用分頁(yè)機(jī)制,那么線性地址直接就是物理地址。Intel 80386的線性地址空間容量為4G(2的32次方即32根地址總線尋址)。
跟邏輯地址類似,它也是一個(gè)不真實(shí)的地址,如果邏輯地址是對(duì)應(yīng)的硬件平臺(tái)段式管理轉(zhuǎn)換前地址的話,那么線性地址則對(duì)應(yīng)了硬件頁(yè)式內(nèi)存的轉(zhuǎn)換前地址。
CPU將一個(gè)虛擬內(nèi)存空間中的地址轉(zhuǎn)換為物理地址,需要進(jìn)行兩步:首先將給定一個(gè)邏輯地址(其實(shí)是段內(nèi)偏移量=),CPU要利用其段式內(nèi)存管理單元,先將為個(gè)邏輯地址轉(zhuǎn)換成一個(gè)線程地址,再利用其頁(yè)式內(nèi)存管理單元,轉(zhuǎn)換為最終物理地址。
由 I NTEL公 司 推 出 的 32 位 80386 芯 片 的 工 作 模 式 包 括 實(shí)地址模式和虛地址模式 。 實(shí)地址模式與8086 完全兼容 . 它的 尋址范圍是1 MB的地址空間. 分段功能受到限制 .不能區(qū)分特權(quán)級(jí) . 當(dāng)然分頁(yè)機(jī)制也不能啟用 。 在虛地址模式下. 分段機(jī) 制得到加強(qiáng) . 段最大可達(dá)4GB. 并且提供段 內(nèi)分頁(yè)管理機(jī)制 . 為 Linux虛擬內(nèi)存管理機(jī)制提供了支持 。
80386 的虛擬地址模式使用了如下分段和分頁(yè)兩級(jí)地址 轉(zhuǎn)換機(jī)制來(lái)實(shí)現(xiàn)虛擬地址向物理地址的轉(zhuǎn)換 。
2 .1 虛擬地址向線性地址的轉(zhuǎn)換
用戶進(jìn)程要訪問(wèn)的虛擬地址包括一個(gè)1 6 位的段選擇器和 一個(gè)32 位的段 內(nèi)偏移 . 80386 的分段機(jī)制將段寄存器中所裝的 段選擇器和32 位段 內(nèi)偏移量相加. 得到32位的線性地址 , 如圖1所示 , 16 位的段選擇器最低兩位表示請(qǐng)求者的特權(quán)級(jí) , 那么 最多可以有16k個(gè)段 , 每段的最大尺寸為4GB。 但是它們都必 須被映射到4GB的線性地址空間。

圖1
2 .2 線性地址向物理地址的轉(zhuǎn)換
Linux的每個(gè)用 戶進(jìn) 程都可 以訪 問(wèn)4 GB的線 性地址空間, 而實(shí)際的物理 內(nèi)存可能遠(yuǎn) 遠(yuǎn)少于4GB. 采用分頁(yè)機(jī)制 。 Linux僅把可執(zhí)行映像的一小部分 裝入物理 內(nèi)存. 當(dāng)需要訪問(wèn)未裝入的頁(yè)面時(shí) . 系統(tǒng)產(chǎn)生一個(gè)缺頁(yè)中斷 , 把需要的頁(yè)讀入 物理內(nèi)存。

圖2
Linux采用兩級(jí)頁(yè)表結(jié)構(gòu)—— 頁(yè)目錄表和頁(yè)表實(shí)現(xiàn)地址 映射. 當(dāng)前正在運(yùn)行進(jìn)程的頁(yè) 目錄表的地址被保存在控制寄 存器 CR3 中。 由上面轉(zhuǎn)換機(jī)制所得到的線性地址可以分為3 部分 , 高 10位是 DI R域—— 頁(yè) 目錄表的索引值 . 它與 CR3 中的地址一起 計(jì)算得到頁(yè)表的物理地址 . 中間1O位保 存相對(duì)于頁(yè)表的索引 值 . 通過(guò)它得到所需的物理頁(yè)號(hào)。 物理頁(yè)號(hào)與低1 2 位頁(yè)內(nèi)偏移 組合得到物理地址 。 其結(jié)構(gòu)如圖2 所示 。
每個(gè)用戶進(jìn)程都可以有4 GB的虛存空 間. 為了更好地管 理這部分虛存空間.Linux主要定義了如下三個(gè)數(shù)據(jù)結(jié)構(gòu) : struct vm_area_struct ,
struct vm_operations_struct struct vmm_struct 虛存段( vm_area_struct ) . 簡(jiǎn)稱 vma是某個(gè)進(jìn)程的一段 連續(xù)的虛存空間. 一個(gè)進(jìn)程通常占用幾個(gè)vma段 . 例如代碼段 、 數(shù)據(jù)段、 堆棧段等 。 vma不僅可以代表一段內(nèi)存區(qū)間, 也可 以對(duì)應(yīng)于一個(gè)文件、 共享內(nèi)存或者對(duì)換設(shè)備。
每一個(gè)進(jìn)程的所有vma由一個(gè)雙向鏈表管理。 為了提高對(duì)vma的查詢、 插入、 刪除等操作的效率 .Linux把系統(tǒng)中所 有進(jìn)程的 vma組成了一棵 AVL樹。 這是一棵平衡二叉樹 . 當(dāng) vma數(shù)量特別 大時(shí)。 利用這棵 AVL樹查找 v ma的效率得到 明顯提 高 。
不同的 vma可能需要不同的操作處理方式 . 但同時(shí)考慮到統(tǒng)接口的統(tǒng) 一 性 . Linux采 用vm_operations_struct結(jié) 構(gòu)和面向?qū)ο蟮乃枷雭?lái)定義操作方式 . 一個(gè)vm_operations_struct結(jié)構(gòu)體是一組 函數(shù)指針 , 對(duì)于不同的 vma . 它可能指向 不同的處理 函數(shù).例如當(dāng)發(fā)生缺頁(yè)錯(cuò)誤時(shí) . 共 享內(nèi)存和代碼 段 的 readpage所 指 向的頁(yè)面讀入函數(shù)可能就不同 。
內(nèi)存管理中另外 一個(gè) 非 常重要的數(shù) 據(jù) 結(jié) 構(gòu)是vmm_struct 結(jié)構(gòu)體 .進(jìn)程 的 task_struct中的mm成員指向 它. 當(dāng)前運(yùn)行進(jìn)程的整個(gè)虛擬空間都 由它來(lái)管理和描述 . 它不僅包含該進(jìn)程的映像信 息. 而且它的 mma p成員項(xiàng)指向該進(jìn) 程所有vma組成的鏈 表 。 它的 mmap_avl 成 員 項(xiàng) 指 向整個(gè)系統(tǒng) 的 AVL樹 。
這三個(gè)數(shù)據(jù)結(jié)構(gòu)之間相互關(guān)聯(lián). 共同管理虛擬內(nèi)存 . 它們之 間的 關(guān) 系如圖 3所 示 。

圖 3
這部分相關(guān)的系統(tǒng)調(diào)用主要有如下兩個(gè) :
- do_mmap(
- struct file *file,
- unsigned long addr
- unsigned long len ,
- unsigned long prot ,
- unsigned long flags ,
- unsigned long off
- );
- find_vma (
- struct mm_struct mm ,
- unsigned long addr
- );
do _mmap函數(shù)實(shí)現(xiàn)了 內(nèi)存映射 。 find_vma函數(shù)的功能 是找到包含參數(shù) addr指定的虛擬地址所屬的 vma 。 當(dāng)要運(yùn)行一個(gè)可執(zhí)行映像時(shí) . 調(diào)用 do _mmap將其裝入 到該進(jìn)程 的虛擬地址空間 . 并且產(chǎn)生一組 vma結(jié)構(gòu) . 如前所 述該進(jìn)程的整個(gè)虛擬空間由 vmm_struct 結(jié)構(gòu)管理 . 但是此時(shí) 可執(zhí)行文件僅僅被連接到進(jìn)程的虛擬空間中. 只有一小部分 頁(yè)面被裝入到物理 內(nèi)存 . 其余大部分并沒(méi)有被真正裝入到物 理內(nèi)存 . 在進(jìn)程的運(yùn)行過(guò)程 中. 產(chǎn)生缺頁(yè)錯(cuò)誤 . 操作 系統(tǒng)首先調(diào)用 find_vma. 找到該虛擬地 址所在的 vma . 然后根據(jù)該 vma的成員變量 vm_ops指向的 vm_operations_struct結(jié)構(gòu) 中的缺頁(yè)操作 函數(shù)。 把頁(yè)裝入物理內(nèi)存。 ·
32位Linux系統(tǒng)的每個(gè)進(jìn)程可以有4 GB的虛擬 內(nèi)存空間 . 而且系統(tǒng)中還要同時(shí)存在多個(gè)進(jìn)程 ,但是 ,事實(shí)上大多數(shù)計(jì)算機(jī)都沒(méi)有這么多物理內(nèi)存空間 , 當(dāng)系統(tǒng)中的物理內(nèi)存緊缺時(shí) . 就需要利用對(duì)換空間把一部分未來(lái)可能不用的頁(yè)面從物理內(nèi)存中移 到對(duì)換設(shè)備或?qū)Q文件中。 Linux采用兩種方式保存換出的頁(yè)面 :
一種是利用整個(gè)塊設(shè)備 , 如硬盤的一個(gè)分區(qū) . 即對(duì)換設(shè)備,
另一種是利用文件系統(tǒng)中固定長(zhǎng)度的文件 . 即對(duì)換文件。 它們統(tǒng)稱為對(duì)換空間。
這兩種方式的相同之處是它們的內(nèi)部格式一致. 但是在執(zhí)行效率方面 . 對(duì)換設(shè)備要好一些. 這是因?yàn)閷?duì)換設(shè)備上同一頁(yè)面 的數(shù)據(jù)塊是連續(xù)存放的 . 故而可以順序存取 , 而在對(duì)換文件中 。 同一頁(yè)面的數(shù)據(jù)塊實(shí)際的物理位置可能是不連續(xù)的 . 需要通過(guò)對(duì)換文件的 inode檢索. 這就降低了存取效率 。
每個(gè)對(duì)換文件或?qū)Q設(shè)備 由 struct swap — info — struct 結(jié)構(gòu)來(lái)描述。 有關(guān)對(duì)換設(shè)備的 函數(shù)主要是 get — swap — page ( …) . 當(dāng)內(nèi)存中的頁(yè)面需要被換出時(shí) . 調(diào)用 get — swap —page函數(shù) 申請(qǐng)得到一個(gè)對(duì)換空間中的物理頁(yè)面 。 如果成功, 就返 回一個(gè)非零代 碼 . 否則返 回0。
Linux使用分頁(yè)管理機(jī)制來(lái)更加有效地利用物理內(nèi)存.當(dāng)創(chuàng)建一個(gè)進(jìn)程時(shí).僅僅把當(dāng)前進(jìn)程的一小部分真正裝入內(nèi) 存.其余部分需要訪問(wèn)時(shí).處理器產(chǎn)生一個(gè)頁(yè)故障.由缺頁(yè)中斷服務(wù)程序根據(jù)缺頁(yè)虛擬地址和出錯(cuò)碼調(diào)用寫拷貝函數(shù)do—wp—page、此地址所屬的vma的vm—ops指向的nopage、do—swap—page.swap—in等函數(shù)將需要的頁(yè)換入物理內(nèi)存。隨著可執(zhí)行映像的運(yùn)行和頁(yè)面的換入.系統(tǒng)中的內(nèi)存有可能變得不足.這時(shí)Linux核心就必須調(diào)用kswapd守護(hù)進(jìn)程釋放部分物理內(nèi)存。kswapd在系統(tǒng)啟動(dòng)時(shí)由init進(jìn)程建立。在系統(tǒng)的運(yùn)行過(guò)程中。它被定期喚醒。檢查系統(tǒng)中的空閑物理內(nèi)存是否很少。如果是.則釋放一部分內(nèi)存.或者將一些頁(yè)面換出到對(duì)換空間。然后繼續(xù)睡眠。
- kswapd 守護(hù)進(jìn)程負(fù)責(zé)確保內(nèi)存保持可用空閑空間。它監(jiān)測(cè)內(nèi)核中的 pages_high 和pages_low 標(biāo)記,如果空閑內(nèi)存空間值小于 pages_low 值, kswwapd 進(jìn)程開始掃描并嘗試每次回收 32 個(gè)頁(yè)面,如此重復(fù)直至空閑內(nèi)存空間大于 pages_high 值。
- kswapd 進(jìn)程履行以下操作:
- * 假如頁(yè)面未改變,它將該頁(yè)面放入 free list。
- * 假如頁(yè)面發(fā)生改變且被文件系統(tǒng)回寫,它將頁(yè)面內(nèi)容寫入磁盤。
- * 假如頁(yè)面發(fā)生改變且未被文件系統(tǒng)回寫(無(wú)名頁(yè)) ,它將頁(yè)面內(nèi)容寫入 swap 設(shè)備。
缺頁(yè)中斷和頁(yè)面換入 頁(yè)面換入主要由缺頁(yè)中斷服務(wù)入口函數(shù)do—page—fault來(lái)實(shí)現(xiàn)。當(dāng)系統(tǒng)中產(chǎn)生頁(yè)面故障時(shí).如果虛擬內(nèi)存地址有效.則產(chǎn)生錯(cuò)誤的原因有如下兩種: 虛擬內(nèi)存地址對(duì)應(yīng)的物理頁(yè)不在內(nèi)存中。那么它必然在磁盤或?qū)Q空間中.如果在磁盤上.那么我們調(diào)用do—nO— page函數(shù).而do—no—page調(diào)用vma一>vm—ops一>nopage()函數(shù)建立頁(yè)面映射.從對(duì)換空間或磁盤中調(diào)入頁(yè)面.或者通過(guò)do—swap—page()函數(shù)調(diào)用swap—in()來(lái)?yè)Q入頁(yè)面。 · 該虛擬地址對(duì)應(yīng)的物理頁(yè)在內(nèi)存。但是被寫保護(hù).如果這種情況發(fā)生在一個(gè)共享頁(yè)面上.則需要“寫拷貝“函數(shù)do— wp—page來(lái)?yè)Q入頁(yè)面.do—wp—page函數(shù)首先調(diào)用一get—free—page獲得一新頁(yè)面.然后調(diào)用copy—COW—page拷貝頁(yè)面的內(nèi)容.當(dāng)然還要調(diào)用相應(yīng)的刷新函數(shù)刷新TLB和緩存等。
頁(yè)交換進(jìn)程和頁(yè)面換出 正如我們上面所描述的.系統(tǒng)使用kswapd守護(hù)進(jìn)程來(lái)定期地?fù)Q出頁(yè)面。使系統(tǒng)中有足夠的空閑物理內(nèi)存頁(yè)。 kswapd進(jìn)程定期地檢查系統(tǒng)中的空閑頁(yè)面數(shù).如果少于一定值.則按照以下三中途徑獲得空閑頁(yè)面:
①減少緩沖區(qū)和頁(yè)面高速緩存的大小;
②把共享內(nèi)存占用的頁(yè)面置換到對(duì)換空間; ③換出或丟棄物理內(nèi)存頁(yè)。
|