Linux 虛存 linux2.6內核特性

1、大型頁面的支持node

    當代計算機體系結構大都支持多種頁面大小,例如,IA-32體系結構支持4KB4MB的頁面, Linux操做系統只是將大型頁面用於映射實際的內核映像。大型頁面的使用主要是爲了改進高性能計算(HPC)以及其餘內存密集型應用的性能。任何佔用大量虛存的訪存密集型應用程序均可以使用大型頁面來改進性能(Linux使用 2MB4MB的大型頁面, AIX使用 16MB的大型頁面,而 Solaris使用的頁面大小爲 4MB)大型頁面可以提升性能是由於轉換查找緩衝區(Translation Lookaside bufferTLB)可以映射到更大的虛存空間(經過增長 TLB的可達範圍),從而減小了 TLB不命中次數。大型頁面經過消除在4KB邊界上重啓預取操做的需求,還改進了內存預取過程 。
    在Linux 2.6內核中,實際可用的大型頁面數量可經過proc(/proc/sys/vm/nr_hugepages)接口來配置。因爲大頁面的實際分配狀況與系統中是否存在着物理連續的內存區域有關,建議在系統啓動時分配大型頁面。 Linux 2.6內核中大型頁面的實現核心稱爲 hugetlbfs,是一種基於 ramfs的僞文件系統(fs/hugetlbfs/inode.c中實現)。該實現的思想使用用大頁面來備份存在於文件系統中的任何文件。實際的僞文件系統在系統啓動時初始化並註冊爲一種內部文件系統。進程訪問大型頁面的方式有兩種:經過 shmget()接口創建一個由大型頁面 back的共享區域,或者經過對一個已在大型頁面文件系統中打開的文件使用mmap()調用。要對一個使用了大型頁面的文件進行操做的話, 首先應掛接一個 hugetlbfs文件系統。完成該掛接操做以後,就可使用標準的文件操做函數調用如 open()等來設置一個文件描述符。 在一個已打開的文件上使用 mmap()系統調用時, hugetlbfs文件系統註冊的 mmap()函數爲該進程建立適當的 vma結構。推薦使用/proc/meminfo接口以確保可以按預期設置大型頁面的容量及數量。分片操做可能會致使該分配過程沒法成功地完成 。

web

2、頁面分配與替換算法

    Linux 2.6內核的物理頁面分配機制仍基於夥伴(buddy)算法,但該機制自己已被擴展, 從而相似於一種將合併過程加以延遲處理的懶夥伴(lazy buddy)機制。合併過程當中的緩衝區釋放活動包含兩個步驟:首先將一個緩衝區推入空閒列表中,使得該緩衝區可用於其餘請求;而後將該緩衝區的引用狀態標記爲空閒(一般在一個位圖之中),並將該緩衝區與相鄰的緩衝區加以合併(若是可行的話)。一般的 buddy系統實如今每次釋放時都會執行這兩個步驟。而 lazy buddy機制執行第一個步驟後延遲執行第二個步驟,是基於緩衝區的狀態來執行該步驟的。下面所討論的懶夥伴概念在 Linux 2.6中的實現採用了基於 CPU的頁面列表。 這些頁面集合包含了兩個頁面(熱頁面和冷頁面)列表, 其中熱頁面是最近已被使用過的頁面,所以指望這些頁面仍存在於 CPUcache中。在分配時, 首先查詢當前 CPU的頁面集合以肯定這些頁面是否可用。若是可用, 則分配過程相應地繼續進行。要肯定應該什麼時候釋放或分配該頁面集合, 則使用一種基於高低水印(low andhigh watermark)的方法。當到達低水印值時,會分配一批頁面並將其置於該表中;當到達高水印值時,會同時釋放一批頁面。這種新型改進實現的結果是極大下降了自旋鎖的開銷。

數組

3、 Slab分配器緩存

    和其餘大多數 UNIX操做系統同樣, Linux也提供了一個通用的內存 slab分配器,用來完成任意空間大小的內存分配。 全部 slab分配器的基本目標都是高效地分配一般小於一個頁面或者不是頁面尺寸偶數倍的小型內存緩衝區。其另外一個目標是對頻繁分配和釋放的內存對象加以操做,這個過程可能致使出現內存分片現象。 slab分配器容許對這些經常使用的對象(例如 sockinodemm_struct)加以緩存,從而儘可能減小每次請求一個新對象時初始化和破壞這些基本實體所需的開銷。 數據結構


4、VM的可調參數
    全部這些參數均可以經過 proc(/proc/sys/vm)文件系統接口進行調優。下面按照與proc文件系統中相同的字母順序列出這些參數。
  • dirty_background_ratio 參數是在嘗試一個回寫(writeback)操做以前所持有的髒內存比例。在 Linux 2.6內核中, pdflush內核線程池負責 VM的回寫操做, 並週期性同步文件系統的元數據。若超出了這個後臺回寫百分比,則 pdflush守護進程異步處理回寫操做。
  • dirty_expire_centisecs 參數是數據能夠保持爲髒狀態的最大釐秒數, 這個時間段經過查詢全部在內存中緩存了髒頁面的文件的時間戳來肯定。該參數表示一個上限值,確保最終能夠將數據寫到磁盤子系統。釐秒錶示1/100s的時間單位。
  • dirty_ratio 參數是過量髒內存的比例。當一個任務在髒內存過多的環境中執行文件寫操做時,系統必需要對髒內存頁面執行寫出操做,直至髒內存頁面的百分比低於系統規定的閾值。這一點很重要, 由於 I/O操做被看做具備高延遲。 若是某個任務在系統可以知足一個分配請求以前須要等待回寫操做完成,則該任務的性能會受到影響。這主要被看做是大型內存系統中的一個問題。
  • dirty_writeback_sentisecs 參數是 pdflush內核線程執行回寫操做之間的時間間隔(以釐秒爲單位)。前面討論過的 dirty_expire_centisecs 參數控制髒內存頁面的存活時間,而該參數定義了 pdflush 線程的調用頻率。建議該參數值小於dirty_expire_centisecs取值(對於多數工做負荷來講, 16的比率應是合理的)。增長這個時間長度以及頻率間隔(但仍遵循 16比率)可能有利於擁有內核密集型工做負荷的大型系統,由於後臺回寫操做可能會干擾到工做負荷自身的性能行爲。
  • lower_zone_protection 參數是爲內存區域回退操做的阻止因子分配的權重。Linux操做系統將物理內存分紅 3個不一樣區域。ZONE_DMA是可由(老式)I/O設備尋址的區域, ZONE_ NORMAL是可由內核尋址的區域, 而 ZONE_HIGHMEM區域則提供給用戶空間和特定的內核(臨時)緩衝區。上述概念的基本原理是ZONE_DMA區域可用做與 ZONE_NORMAL相同的用途,而 ZONE_NORMAL區域可用做與 ZONE_HIGHMEM 相同的用途,但反之則否則。當ZONE_HIGHMEM區域飽和時, 可使用 ZONE_NORMAL區域進行分配(經過一個回退操做)ZONE_NORMAL是惟一可用於保存內核數據結構的區域,對於系統而言是相當重要的。在Linux中,使用一種稱爲遞增最小量(incremental min)的啓發算法來阻止回退至重要內存區域(至少 ZONE_NORMAL)。lower_zone_protection置爲默認的零值會禁止遞增最小量算法,將該參數值設置爲 4會使其效果增至4倍。這意味着該參數當前控制較低區域防禦算法的強度。對於可能佔用系統中較高區域的分配操做,lower_zone_protection這個可調參數能夠提升對較低內存區域的保護程度 。
  • min_free_kbytes 參數規定了可用於諸如中斷處理程序發起的緊急分配等的內存池的大小。在更大規模的系統上, 該參數會影響可用於中斷時間的內存與可用於運行時分配的內存比率。在更小的內存系統上, 該參數被保持爲較小值以免分配失敗。廣泛共識是這個低水印參數用於肯定什麼時候拒絕用戶空間分配以及什麼時候激發頁面替換場景。有可能不將該值設置爲任何較大的物理內存比例。若是用戶空間操做是內存子系統主要消耗者,尤爲適用。
  • nr_pdflush_thread 參數規定 pdflush(回寫)線程池的當前大小。VM子系統利用一種動態算法來斷定實際線程的數量。重點是在低內存的情形下(其中額外線程的動態分配可能會失敗)保留特定數量的 pdflush線程。下限與上限(Linux中分別稱爲 MIN_PDFLUSH_THREADSMAX_PDFLUSH _THREADS)各自設置爲 28。提升上限值(而且重編譯內核)有助於在擁有大量磁盤驅動器以及綁定尋道操做的工做負荷的環境中提升 VM I/O併發性。提升最大值會改進性能的另外一種狀況是與回寫操做相關的 CPU綁定情形,這時系統中可提供額外處理器來處理整體工做負荷。
  • overcommit_memory 參數是一個容許內存過量使用的標誌。當該標誌置爲默認值 0時,內核在每一個 malloc()調用前都發起檢查以確保存在足夠的內存。若該標誌置爲 1,則假定系統中老是存在着足夠多的內存。當該標誌置爲 0時,則確保只會分配頁面替換基礎架構所能處理的用戶虛存量,而且每一個頁面都須要一個後備存儲器。匿名內存頁面須要交換空間,而文件頁面則須要能夠被保留的磁盤空間。將該標誌置爲1後會生成更有效的內存利用行爲。可是,基於特定工做負荷,它可能致使某些進程被關閉的場景。概言之,將該標誌置爲 0會致使內核經過估測可用的內存量和明顯無效的失敗請求,執行啓發式的內存過量使用處理操做。不幸的是,因爲系統使用一種啓發式而不是精確的算法來分配內存,這種設置有時會致使系統可用內存過載。將該標誌置爲 1會致使內核執行內存無過量使用方式的處理。這種設置會增大內存過載的可能性,但也會提升內存密集型任務(例如某些科學應用所執行的任務)的性能。另外一種支持情形是將該標誌置爲2。在這種狀況下,對於所有交換空間以及 overcommit_ratio 參數(在下面討論)中規定的物理內存百分比之和的內存請求,內核會分配失敗。 在 Linux中, 將該標誌置爲2能夠下降內存過量使用的風險。
  • overcommit_ratio 參數指定了當(前面討論的)overcommit_memory參數置爲2時所考慮的物理內存百分比。默認值是50
  • page-cluster 參數所表明的整數值當 2做爲 x的乘冪時標識了內核一次性讀入的頁面數目(實際的交換預讀窗口)。該參數的默認值對於內存小於 16MB的系統爲 2,對於內存更大的系統爲3, 這些取值在多數狀況下均可看做是合理的設置。 該參數可用於改進頁面 I/O效率, 但若是該參數被不當指定的話, 系統可能會面臨過分的I/O和內存消耗。
  • swappiness 參數指示了 VM子系統在經過解除頁面映射並將其換出的方式來回收頁面與只回收未被任何進程映射的頁面之間的相對優先選擇。實際的決策依賴於一個二元開關,當映射至進程頁表中的內存百分比的一半取值與 swappiness取值之和超過 100時激活該開關。 系統在決策過程當中進一步利用了某個危機因子,該因子在每次須要重試頁面替換操做時都增長 2倍。若是系統難以定位可回收的未映射頁面,則 VM子系統執行反向工做過程並開始對匿名內存進行頁換出。若是不想對匿名內存進行頁換出,則能夠經過爲 swappiness參數賦予較低取值來表達。若是 kswapd正在使用大量 CPU資源或者系統正在 iowait狀態中耗費時間,則能夠增長 swappiness參數值能夠提升系統的總體性能。

5、CPU調度器
    線程調度器子系統負責將可用的 CPU資源分配到可運行的線程中。該調度器的行爲及決策制定過程與線程的公平性和調度延遲直接相關。公平性可描述爲全部線程不只都可以向前執行並且都以一種均衡的方式向前執行的能力。公平性的相反狀況稱爲餓死,在這種情形下某個特定線程沒法繼續向前執行。公平性經常難以評判,由於這意味着全局和局部性能間的折衷。調度延遲描述了線程進入可運行狀態(TSRUN)後以及在處理器上實際運行(TSONPROC)之間的實際延遲。低效的調度延遲行爲會致使應用響應時間出現明顯的遲滯。高效且有效的 CPU調度器對於計算平臺的運行極爲重要, 決定了每一個任務(線程)在什麼時候開始運行以及運行的時間長度。 實時任務與分時任務是有區別的, 各自具備不一樣的目標,並經過調度器中內含的不一樣調度規則來實現。
    Linux爲每一個任務分配一個靜態優先級,能夠經過 nice()接口對其進行修改。 Linux擁有一組優先級類型,用以區別實時任務和分時任務。優先級的取值越低, 任務的邏輯優先級或者換句話說其綜合重要性(general importance)就越高。當闡述優先級提升或下降時,在這個上下文中的討論老是指代邏輯優先級。實時任務的優先級老是高於分時任務。
    Linux 2.6內核的調度器稱爲 O(1)調度器,是一個多隊列調度器,爲每一個 CPU都分配一個實際的運行隊列, 所以是一種 CPU本地調度方法。 O(1)這個標籤描述了任務檢索的時間複雜度,即不管系統上的工做負荷如何,均可以在常量時間內選定下一個運行任務。
    先前版本的
Linux調度器使用了優度(goodness)概念來肯定下一個待執行的線程。全部可運行的任務都保持在單個運行隊列上,該隊列是處於 TSRUN(TASK_RUNNABLE)狀態中的線程所造成的一個鏈表。 Linux 2.6內核中將惟一的運行隊列鎖替換爲基於每一個CPU的鎖,從而確保在 SMP系統上具備更好的擴展性。該 O(1)調度器所採用的基於 CPU的運行隊列機制將運行隊列(按優先級順序)分解成許多桶(bucket),並使用位圖來標識擁有可運行任務的那些桶。若是要定位下一個待執行任務,須要讀取該位圖以標識出第一個具備可運行任務的桶並選擇該桶的運行隊列中的第一個任務。
    每一個
CPU的運行隊列由兩個任務列表向量組成, 稱爲活躍向量(active vector)和超時向量(expired vector)。每一個向量索引表明了擁有各自優先級的可運行任務的一個列表。一個任務在執行一段時間後,會從活躍列表移至超時列表,這樣確保了全部可運行任務都可以得到執行機會。當該活躍數組爲空時, 則經過修改指針來交換超時向量和活躍向量。
    系統有時須要執行一個負載平衡算法對各個運行隊列進行平衡處理,以確保每一個
CPU上的任務數量都相近。前面提過,調度器須要決定即將運行哪些任務以及任務的運行時間長度。Linux內核中的時間量子定義爲系統節拍的倍數。節拍定義爲兩個連續定時器中斷之間的固定增量(1/HZ)Linux 2.6內核中, 參數 HZ被設置爲 1 000, 這代表每毫秒激活一次中斷例程 scheduler_tick(),此時當前運行的任務即執行了一個節拍。將參數 HZ被設置爲 1 000並不會改進系統的響應效率,由於該設置不會影響到實際的調度器時間片。對於主要在數學運算(number-crunching)模式中執行的系統來講,HZ=1 000的設置可能並不合適。在這種環境下,將參數 HZ設置爲更低的取值(大約 100)有利於提升總體系統的性能。
    除了靜態優先級
(static_prio)以外,每一個任務都還維護一個有效優先級(prio)其區別表示基於特定任務的最近平均休眠時間(sleep_avg)而獲得的特定優先級獎勵或處罰。平均休眠時間表示一個任務最近被取消調度的節拍數量。任務的有效優先級決定了其在運行隊列的優先級列表中的位置。若是一個任務的有效優先級超出其靜態優先級特定程度,則稱該任務是交互式的。這種場景只能基於任務 accumulating平均休眠節拍數。Linux 2.6內核中嵌入的交互式估測器框架自動且透明地運行。在 Linux中,高優先級任務到達交互狀態所需的平均休眠時間遠小於低優先級任務。由於基於平均休眠時間來評估任務的交互性, I/O綁定的任務是到達交互狀態的潛在候選,而 CPU綁定的任務一般不被當作是交互式的。實際的時間片被定義爲一個任務在將 CPU(主動)轉讓給另外一個任務以前能夠執行的最長時間,只是正常任務的靜態優先級的線性函數。 優先級自己對應於MIN_TIMESLICE(默認值爲10ms)MAX_TIMESLICE(默認值200ms)之間的時間值。一個任務的優先級越高,該任務的當前時間片所減小的每一個定時器節拍的時間量就越大。當時間量減至 0時,調度器再次補充時間片數據,從新計算有效優先級,並將該任務從新排隊到活躍向量(若該任務被歸類爲交互式的)或超時向量(若該任務被看做是非交互式的)中。 此時, 系統會從活躍數組中分派另外一個任務。 該場景確保了在任何超時任務得到再次運行的機會前,首先執行活躍數組中的任務。若是一個任務被取消調度的話,則在喚醒時不會補充時間片數據,可是其有效優先級可能因爲任何 accumulated休眠時間而已經發生變化。若是全部可運行任務都耗盡了本身的時間片並已被移至超時列表中,則應交換超時和活躍向量。 這種技術使得該 O(1)調度器不須要遍歷一個可能很長的任務列表(這是 Linux 2.4內核調度器中所需的操做)。這種新型設計的問題是,因爲任何潛在的交互行爲,如下場景可能會出現:活躍隊列繼續擁有未被移入超時列表的可運行任務。有 些任務可能由於等待 CPU時間而中止。爲了不這個問題, 首先移入超時列表中的任務要老於 STARVATION_LIMIT(10),而且應交換活躍數組和超時數組。
相關文章
相關標籤/搜索