1. 程式人生 > 其它 >Linux核心記憶體管理:快取系統

Linux核心記憶體管理:快取系統

快取記憶體是將頻繁訪問或新寫入的資料從一個小而快的記憶體中取出或寫入的過程,這個過程稱為快取記憶體。

髒記憶體是資料支援的(例如檔案支援的)記憶體,其內容已被已修改(通常在快取中)但尚未寫回磁碟。 快取的版本資料比磁碟版本新,這意味著兩個版本不同步。 將快取資料寫回磁碟(後備儲存)的機制稱為回寫。 我們最終將更新磁碟版本,使兩者同步。 乾淨的記憶體是檔案支援的記憶體,其中的內容與磁碟同步。

Linux 延遲寫入操作以加快讀取過程,並通過僅在必要時寫入資料來減少磁碟磨損均衡。 一個典型的例子是 dd 命令。 它的完整執行並不意味著將資料寫入目標裝置; 這就是為什麼 dd 在大多數情況下連結到同步命令的原因。

什麼是快取?

快取是臨時的、小而快的記憶體,用於從較大且通常非常慢的記憶體中儲存資料副本,通常放置在系統中,其中工作資料集的訪問頻率遠高於其他資料集(例如,硬碟驅動器、 記憶)。

當第一次讀取發生時,假設一個程序從較大且較慢的磁碟請求一些資料,請求的資料將返回給程序,並跟蹤和快取訪問資料的副本。任何後續讀取都將從快取中獲取資料。任何資料修改都將應用在快取中,而不是主磁碟上。然後,內容已被修改且與磁碟版本不同(比磁碟版本更新)的快取區域將被標記為dirty。當快取執行滿時,由於快取的資料被新增,新的資料開始驅逐未被訪問且閒置時間最長的資料,因此,如果再次需要它,它將不得不再次從大/慢的儲存中提取。

CPU快取記憶體-記憶體快取記憶體

在現代的CPU上有三個快取儲存器,按大小和訪問速度排序:

  • L1快取擁有最小的記憶體(通常在1K到64K之間),並且可以在一個時鐘週期內被CPU直接訪問,這使得它也是最快的。經常使用的東西都在L1中,直到其他東西的使用頻率比現有的多,L1中的空間變少到不夠用為止。如果L1不夠用了,它被移動到一個更大的L2。
  • L2快取是中間層,與處理器相鄰的記憶體數量較大(可達幾兆位元組),可以在少量的時鐘週期內訪問。這適用於從L2移動物體到L3。
  • L3快取雖然比L1和L2慢,但速度可能是主存(RAM)的兩倍。每個核心可能有自己的L1和L2快取;因此,它們都共享L3快取。大小(L1 < L2 < L3)和速度(L1 > L2 > L3)是每個快取級別之間變化的主要標準。例如,原始記憶體訪問可以是100 ns, L1快取訪問可以是0.5 ns。

一個現實生活中的例子是,圖書館為了方便快捷地獲取最受歡迎的圖書,可能會展示幾本,但卻有一個規模更大、可獲得的藏書更多的檔案,這很不方便,因為你不得不等待圖書管理員去取。陳列櫃類似於快取,而存檔則是大而慢的記憶體。

CPU快取解決的主要問題是延遲,這間接地增加了吞吐量,因為訪問未快取記憶體可能需要一段時間。

Linux頁面快取-磁碟快取

顧名思義,頁面快取是RAM中的頁面快取,其中包含最近訪問的檔案塊。RAM充當駐留在磁碟上的頁的快取。換句話說,它是檔案內容的核心快取。快取的資料可能是常規的檔案系統檔案、塊裝置檔案或記憶體對映檔案。每當呼叫read()操作時,核心首先檢查資料是否駐留在頁面快取中,如果找到就立即返回。否則,將從磁碟讀取資料。

如果一個程序需要在不涉及快取的情況下寫入資料,它必須使用O_SYNC標誌,它保證write()命令在所有資料傳輸到磁碟之前不會返回,或者O_DIRECT標誌,這隻能保證資料傳輸不會使用快取。也就是說,O_DIRECT實際上取決於所使用的檔案系統,不推薦使用。

專用快取(使用者空間快取)

  • 網路瀏覽器快取: 它將經常訪問的網頁和影象儲存到磁碟上,而不是從網路獲取它們。儘管線上資料的第一次訪問可能持續數百毫秒以上,但第二次訪問將在僅10毫秒內從快取(在本例中是磁碟)中獲取資料。
  • libc或使用者應用程式快取:記憶體和磁碟快取實現將嘗試猜測您接下來需要使用什麼,而瀏覽器快取保留一個本地副本,以備再次使用。

為什麼延遲向磁碟寫入資料?

主要有兩個原因:

  • 更好地利用磁碟特性;這是效率
  • 允許應用程式在寫入後立即繼續;這是效能

例如,延遲磁碟訪問和處理資料直到資料量達到一定的大小,可以提高磁碟效能,降低嵌入式系統的eMMC磨損水平。每個塊的寫合併為一個單獨的連續的寫操作。此外,寫入的資料被快取,允許程序立即返回,以便任何後續讀取都將從快取中獲取資料,從而使程式響應更快。儲存裝置更傾向於少量的大操作,而不是一些小操作。

通過稍後執行對永久儲存的寫操作,我們可以消除這些磁碟帶來的延遲問題,這些磁碟相對較慢。

寫快取策略

根據快取策略的不同,可以列舉出幾個好處:

  • 降低資料訪問延遲,從而提高應用程式效能
  • 提高儲存的生命週期
  • 減少系統工作負載
  • 降低資料丟失的風險

快取演算法通常分為以下三種不同的策略:

  1. write-through cache是任何寫操作都會自動更新記憶體快取和永久儲存。對於不能容忍資料丟失的應用程式,以及寫資料然後頻繁地重新讀取資料的應用程式(因為資料儲存在快取中,因此讀延遲較低),這種策略是首選。
  2. write-aroundcache write-through cache類似,不同之處在於它會立即使快取失效(這對系統來說也很昂貴,因為任何寫都會導致快取自動失效)。主要的結果是,任何後續的讀取都將從磁盤獲取資料,這是緩慢的,從而增加了延遲。它防止快取被隨後無法讀取的資料淹沒。
  3. Linux 採用第三種也是最後一種策略,稱為回寫快取(write-back cache),它可以在每次發生變化時將資料寫入快取,而無需更新主存中相應的位置。相反,頁面快取中相應的頁面被標記為dirty(該任務由MMU使用TLB完成),並被新增到一個由核心維護的所謂列表中。只有在指定的時間間隔或特定的條件下,資料才被寫入到永久儲存器中相應的位置。當頁面中的資料與頁面快取中的資料一致時,核心將從列表中刪除這些頁面,它們不會被標記為dirty。
  4. 在Linux系統中,你可以在/proc/meminfo中找到Dirty:
cat /proc/meminfo | grep Dirty

重新整理執行緒(flusher threads)

回寫cache 延遲I/O資料在頁cache中的操作。一組或核心執行緒(稱為重新整理執行緒)負責此工作。當滿足下列任何一種情況時,髒頁回寫發生:

  • 當空閒記憶體低於指定的閾值以重新獲得髒頁所消耗的記憶體時。
  • 髒資料持續到指定時間段。將最老的資料寫回磁碟,以確保髒資料不會無限期保持髒。
  • 當用戶程序呼叫sync()和fsync()系統呼叫時。這是按需回寫。