當(dāng)頁面塊被釋放時,代碼將檢查是否有相同大小的相鄰或者buddy內(nèi)存塊存在 。如果有,則將它們結(jié)合起來形成一個大小為原來兩倍的新空閑塊 。每次結(jié)合完之后,代碼還要檢查是否可以繼續(xù)合并成更大的頁面 。最佳情況是系統(tǒng)的空閑頁面塊將和允許分配的最大內(nèi)存一樣大 。
在圖3.4中,如果釋放頁面框號1,它將和空閑頁面框號0結(jié)合作為大小為2個頁面的空閑塊排入free_area的第一個元素中 。
3.5內(nèi)存映射
映象執(zhí)行時,可執(zhí)行映象的內(nèi)容將被調(diào)入進(jìn)程虛擬地址空間中 ??蓤?zhí)行映象使用的共享庫同樣如此 。然而可執(zhí)行文件實(shí)際上并沒有調(diào)入物理內(nèi)存,而是僅僅連接到進(jìn)程的虛擬內(nèi)存 。當(dāng)程序的其他部分運(yùn)行時引用到這部分時才把它們從磁盤上調(diào)入內(nèi)存 。將映象連接到進(jìn)程虛擬地址空間的過程稱為內(nèi)存映射 。
圖3.5 虛擬內(nèi)存區(qū)域
每個進(jìn)程的虛擬內(nèi)存用一個mm_struct來表示 。它包含當(dāng)前執(zhí)行的映象(如BASH)以及指向vm_area_struct 的大量指針 。每個vm_area_struct數(shù)據(jù)結(jié)構(gòu)描敘了虛擬內(nèi)存的起始與結(jié)束位置,進(jìn)程對此內(nèi)存區(qū)域的存取權(quán)限以及一組內(nèi)存操作函數(shù) 。這些函數(shù)都是Linux在操縱虛擬內(nèi)存區(qū)域時必須用到的子程序 。其中一個負(fù)責(zé)處理進(jìn)程試圖訪問不在當(dāng)前物理內(nèi)存中的虛擬內(nèi)存(通過頁面失效)的情況 。此函數(shù)叫nopage 。它用在Linux試圖將可執(zhí)行映象的頁面調(diào)入內(nèi)存時 。
可執(zhí)行映象映射到進(jìn)程虛擬地址時將產(chǎn)生一組相應(yīng)的vm_area_struct數(shù)據(jù)結(jié)構(gòu) 。每個vm_area_struct數(shù)據(jù)結(jié)構(gòu)表示可執(zhí)行映象的一部分:可執(zhí)行代碼、初始化數(shù)據(jù)(變量)、未初始化數(shù)據(jù)等等 。Linux支持許多標(biāo)準(zhǔn)的虛擬內(nèi)存操作函數(shù),創(chuàng)建vm_area_struct數(shù)據(jù)結(jié)構(gòu)時有一組相應(yīng)的虛擬內(nèi)存操作函數(shù)與之對應(yīng) 。
3.6請求換頁
當(dāng)可執(zhí)行映象到進(jìn)程虛擬地址空間的映射完成后,它就可以開始運(yùn)行了 。由于只有很少部分的映象調(diào)入內(nèi)存,所以很快就會發(fā)生對不在物理內(nèi)存中的虛擬內(nèi)存區(qū)域的訪問 。當(dāng)進(jìn)程訪問無有效頁表入口的虛擬地址時,處理器將向Linux報告一個頁面錯誤 。
頁面錯誤帶有失效發(fā)生的虛擬地址及引發(fā)失效的訪存方式 。Linux必須找到表示此區(qū)域的vm_area_struct結(jié)構(gòu) 。對vm_area_struct數(shù)據(jù)結(jié)構(gòu)的搜尋速度決定了處理頁面錯誤的效率,而所有vm_area_struct結(jié)構(gòu)是通過一種AVL(Adelson-Velskii and Landis) 樹結(jié)構(gòu)連在一起的 。如果無法找到vm_area_struct與此失效虛擬地址的對應(yīng)關(guān)系,則系統(tǒng)認(rèn)為此進(jìn)程訪問了非法虛擬地址 。這時Linux將向進(jìn)程發(fā)送SIGSEGV信號,如果進(jìn)程沒有此信號的處理過程則終止運(yùn)行 。
如果找到此對應(yīng)關(guān)系,Linux接下來檢查引起該頁面錯誤的訪存類型 。如果進(jìn)程以非法方式訪問內(nèi)存,比如對不可寫區(qū)域進(jìn)行寫操作,系統(tǒng)將產(chǎn)生內(nèi)存錯誤的信號 。
如果Linux認(rèn)為頁面出錯是合法的,那么它需要對這種情況進(jìn)行處理 。
首先Linux必須區(qū)分位于交換文件中的頁面和那些位于磁盤上的可執(zhí)行映象 。Alpha AXP的頁表中有可能存在有效位沒有設(shè)置但是在PFN域中有非0值的頁表入口 。在這種情況下,PFN域指示的是此頁面在交換文件中的位置 。如何處理交換文件中的頁面將在下章討論 。
不是所有的vm_area_struct數(shù)據(jù)結(jié)構(gòu)都有一組虛擬內(nèi)存操作函數(shù),它們有的甚至沒有nopage函數(shù) 。這是因?yàn)椤inux通過分配新的物理頁面并為其創(chuàng)建有效的頁表入口來修正這次訪問 。如果這個內(nèi)存區(qū)域存在nopage操作函數(shù),Linux將調(diào)用它 。
一般Linux nopage函數(shù)被用來處理內(nèi)存映射可執(zhí)行映象,同時它使用頁面cache將請求的頁面調(diào)入物理內(nèi)存中去 。
當(dāng)請求的頁面調(diào)入物理內(nèi)存時,處理器頁表也必須更新 。更新這些入口必須進(jìn)行相關(guān)硬件操作,特別是處理器使用TLB時 。這樣當(dāng)頁面失效被處理完畢后,進(jìn)程將從發(fā)生失效虛擬內(nèi)存訪問的位置重新開始運(yùn)行 。
推薦閱讀
- 以Linux做路由器的問題
- Linux 核心--1.前言
- 紅豆糖水的功效與作用 紅豆糖水的功效與作用禁忌
- Linux 核心--3.軟件基礎(chǔ)
- 認(rèn)識Linux操作系統(tǒng)下三大便利開源防火墻
- 如何在Linux中設(shè)置磁盤限額?
- Linux下的各種備份方法匯總
- Linux 內(nèi)核解讀入門
- linux使用經(jīng)驗(yàn)點(diǎn)滴
- 安裝 Linux 無盤工作站
