Linux Swap機制概述

2021-07-26 10:52:56 字數 4178 閱讀 9302

1.      頁框**演算法(pfra)將頁分為不可**頁、可交換頁、可同步頁、可丟棄頁四種型別。其中,可交換頁包括:

i.屬於程序匿名線性區(如使用者態堆、棧)的頁;

ii.屬於程序私有記憶體對映的髒頁;

iii.屬於ipc共享記憶體區的頁;

對於記憶體中的每一頁,核心利用頁表項中的present標誌來判斷該頁是否被換出。

2.對映頁是指映**乙個檔案的某一部分的頁,使用者態位址空間中屬於檔案記憶體對映的所有頁和頁快取記憶體(page cache)中的頁都是對映頁;匿名頁是指它屬於乙個程序的某匿名線性區,例如,程序的使用者態堆和堆疊中的所有頁為匿名頁。頁描述符1.      每個交換區都由一組頁槽(page slot)組成,即一組大小為4096位元組的塊組成,每塊中包含乙個換出的頁。每個交換區由乙個或多個交換子區組成,每個交換子區由乙個swap_extent描述符表示,每個子區對應的一組頁槽在磁碟上是物理相鄰的。存放在磁碟分割槽中的交換區只有乙個子區,而存放在普通檔案中的交換區則可能有多個子區,這是因為該檔案在磁碟上可能不在一組連續塊中。

2.交換區描述符。每個活動的交換區在記憶體中都有自己的swap_info_struct描述符,其主要字段如下:

字段

說明

flags

交換區標誌

swap_map

指向計數器陣列的指標,每個陣列元素對應交換區的每個頁槽

lowest_bit

搜尋乙個空閒頁槽時要掃瞄的第乙個頁槽

highest_bit

搜尋乙個空閒頁槽時要掃瞄的最後乙個頁槽

cluster_nr

已分配的空閒頁槽數

cluster_next

搜尋乙個空閒頁槽時要掃瞄的下乙個頁槽

prio

交換區優先順序

pages

可用頁槽的個數

max以頁為單位的交換區大小

inuse_pages

交換區內已用頁槽數

next

指向下乙個交換區描述符的指標

flags欄位的swp_used和swp_writeok標誌表示交換區是否是活動的可寫入的;

swap_map字段指向乙個計數器陣列,交換區的每乙個頁槽對應乙個元素。如果計數器值等於0,那麼這個頁槽就是空閒的;如果計數器為正數,則頁槽計數器的值就表示共享換出頁的程序數;

cluster_nrcluster_next字段相結合用於查詢空閒頁槽,如果cluster_nr欄位為正,則下次查詢從cluster_next開始,若cluster_nr為0則從lowest_bit開始查詢;

lowest_bithighest_bit分別表示第乙個和最後乙個可能為空的頁槽,即所有低於lowest_bit和高於highest_bit的頁槽都被認為是已經分配過); 3.

swap_info陣列包括max_swapfiles個交換區描述符,只有設定了swp_used標誌的交換區才被使用。活動的交換區描述符也被插入按交換區優先順序排序的swap_list鍊錶中。該鍊錶是通過交換區描述符的next欄位實現的,next欄位存放的是swap_info陣列中下乙個描述符的索引。swapon()和swapoff()系統呼叫用於啟用和禁用交換區。

換出頁識別符號是由區號頁槽索引構成的,分別表示交換區在swap_info陣列中的索引以及頁槽在交換區內的索引,這樣就可以唯一標識乙個頁槽。swp_entry(type,offset)巨集負責從交換區索引type和頁槽索引offset中構造換出頁識別符號。swp_type和swp_offset巨集作用相反。當頁被換出時,其識別符號就作為頁的表項插入頁表中,這樣在需要時就可以找到這個頁,因此,乙個頁表項就可能存在下列三種情況(頁表項的最後一位即為present標誌):

i.     空項:該頁不屬於程序的位址空間,或相應的頁框還沒有分配給程序;

ii.    前31位不全等於0,最後一位等於0:該頁被換出;

iii.   最低位等於1:該頁包含在ram中;

1.      查詢乙個空閒頁槽。scan_swap_map()函式進行查詢操作,linux採用一種混合策略,即大多數情況下(cluster_nr為正數)會從cluster_next開始查詢,而在已經到達交換區末尾或需重新開始分配時(上次從頭開始分配之後,已經分配了swapfile_cluster=256個空閒頁槽),則從lowest_bit開始查詢。若找不到空項的頁槽,則置lowest_bit欄位為最大索引,highest_bit為0,以表示交換區已滿。所有的查詢都是對計數器陣列swap_map進行的。

(如果交換區已滿並且記憶體也不足,頁框**演算法會負責結束程序來**記憶體,交換只負責暫時存放未用頁以釋放記憶體,它頁框**演算法的乙個子集) 2.

get_swap_page()函式通過搜尋所有活動的交換區(swap_list鍊錶)來查詢乙個空閒頁槽,該函式主要還是通過scan_swap_map()函式來獲得乙個空閒頁槽。swap_free()函式執行swap_map計數器的減1操作,當計數器值為0時表示頁槽變為空閒,此時應修改交換區描述符的相應字段。

1.swap cache的引入解決同步的問題,例如兩個程序可能同時要換入同乙個匿名共享頁,或者乙個程序可能同時進行換入換出操作。對於第一種情況,換入操作的頁必須先存在swap cache上,因此可以通過頁描述符的pg_locked標誌標誌來避免競爭;而對於第二種情況,假定程序a、b共享乙個頁p,當頁p需要被換出時,先將其移動到swap cache上,再將a、b的頁表項修改,此時,頁框p只被swap cache所引用,這時候分兩種情況:(1)此時若有換入操作需執行(例如程序b需要將該頁寫入磁碟),由於程序b產生page fault,而缺頁處理程式發現頁框p在swap cache中,則它直接將頁框p的實體地址插入程序b的頁表項(而沒有必要重新分配頁,再換入頁槽中的資料);(2)若此時沒有換入操作,則swap cache會刪除對該頁框p的引用並把它釋放到夥伴系統。swap cache有一組輔助函式來支援上層的呼叫。

2.swap cache是由page cache實現的,其核心資料結構就是radix tree,交換快取記憶體中頁的存放方式是隔頁存放,並具有以下特徵:

ii. 頁描述符的pg_swapcache標誌置位;

iii. private欄位存放與該頁有關的換出頁識別符號;

3.1.換出頁操作的第一步是準備swap cache,如果頁框**演算法(shrink_list()函式)確定某頁是匿名頁且不在swap cache中,核心就呼叫add_to_swap()函式,該函式在交換區分配乙個新頁槽,並把頁框插入swap cache;然後更新引用該匿名頁的所有頁表項;接著就是把頁的資料寫入交換區,這是真正的i/o傳輸操作,由pageout()函式呼叫頁address_space物件的writepage()方法實現,該步i/o傳輸結束後還需進行喚醒相關程序,清除標記等工作;最後核心試圖將swap cache中的頁框釋放到夥伴系統。

2.

swap thrashing是指頁頻繁的寫入磁碟再從磁碟讀入,大部分時間消耗在訪問磁碟上,核心解決該問題的方法是把swap token賦給系統中的單個程序,該標記使得程序免於頁框**。當程序擁有交換標記是,swap_token_mm被設為程序的記憶體描述符的位址。當程序要從交換區讀入乙個頁時,grab_swap_token函式決定是否將交換標記賦給當前程序。handle_pte_fault()函式呼叫do_swap_page()函式執行換入頁操作,函式首先檢查swap cache中是否存在該頁,如果沒在,則呼叫swap_readpage()從交換區讀入頁資料到swap cache中,然後完成相應的工作。

Linux swap空間問題

我們知道linux做虛擬記憶體交換的空間叫做swap空間.我們也知道,如果swap劃分太小了,ram用完了swap也用完了系統就可以崩潰了.所以我們在swap用完之前有什麼可以快速解救的辦法沒有呢?當然是有的 方法1 從其他的分割槽劃分空間新增到swap分割槽 我們可以使用fdisk命令輕易的將其他...

永久關閉linux swap

一般來說,linux的虛擬記憶體會根據系統負載自動調整。記憶體頁 page swap到磁碟會顯著的影響kafka的效能,並且kafka重度使用page cache,如果vm系統swap到磁碟,那說明沒有足夠的記憶體來分配page cache。另外一種方式是通過核心調節 髒頁 注 髒頁 會被刷到磁碟上...

sqlite鎖機制概述

sqlite的鎖的粒度比較粗,是資料庫級別的,也就是說即使只是對某個頁進行讀寫操作,sqlite也會封鎖整個資料庫。這種策略降低了讀 寫事務和寫 寫事務間的併發程度,但是大大簡化了程式設計,減小了整個程式的大小。所以,sqlite的適用場景為 較少次寫入資料,大量 多次讀出資料。這也是sqlite作...