<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          LWN:利用page folio來明確內(nèi)存操作!

          共 3742字,需瀏覽 8分鐘

           ·

          2021-04-07 10:39

          關(guān)注了就能看到更多這么棒的文章哦~

          Clarifying memory management with page folios

          By Jonathan Corbet
          March 18, 2021
          DeepL assisted translation
          https://lwn.net/Articles/849538/

          內(nèi)存管理(memory management)一般是以 page 為單位進(jìn)行的,一個(gè) page 通常包含 4,096 個(gè)字節(jié),也可能更大。內(nèi)核已經(jīng)將 page 的概念擴(kuò)展到所謂的 compound page(復(fù)合頁),即一組組物理連續(xù)的單獨(dú) page 的組合。這又使得 "page" 的定義變得有些模糊了。Matthew Wilcox 從去年開始就一直在研究一個(gè)叫做 "page folios" 的概念,希望能讓人們重新關(guān)注這個(gè)問題。不過,目前還不清楚內(nèi)存管理社區(qū)是否會(huì)接受這個(gè)概念。

          從最底層來說,page 是一個(gè)由硬件實(shí)現(xiàn)的概念。對(duì)內(nèi)存的跟蹤以及判定是否位于 RAM 中這都是以 page 為基本單位來進(jìn)行的。無論是哪種 CPU 架構(gòu),盡管可能會(huì)提供有限幾種 page size,但一定會(huì)從中選擇一個(gè) "base" page size,最常見的選擇仍然是 4,096 字節(jié)——這與 30 年前第一個(gè) Linux 內(nèi)核發(fā)布時(shí)的情況一樣。

          不過,內(nèi)核經(jīng)常需要獲取更大塊的內(nèi)存(memory in larger chunks)。其中一個(gè)例子是管理 "huge pages",huge page 同樣也是由硬件實(shí)現(xiàn)的。例如,x86 架構(gòu)可以使用 2MB 的 huge page,在恰當(dāng)?shù)牡胤绞褂?huge page 可以提高性能。內(nèi)核也會(huì)分配用其他 size 為單位來分配一組 page,通常是用于 DMA buffer 或其他那些需要使用連續(xù)的若干 page 的場(chǎng)景下。這種頁面分組(grouping of pages)在內(nèi)核中被稱為 "compound page(復(fù)合頁)"。

          內(nèi)核所管理的內(nèi)存中,每一個(gè) base page 都是用 system memory map 中的一個(gè) page structure 來代表的。如果利用一組 base page 創(chuàng)建出了一個(gè) compound page,那么就會(huì)對(duì)這組 pages 中的第一個(gè) page("head page")的 page structure 打上一個(gè)特殊標(biāo)記,從而明確指出這是一個(gè) compound page。這個(gè) head page 的 page structure 中的其他信息都是對(duì)整個(gè) compound page 生效的。所有其他 page("tail pages")也都被標(biāo)記出來,使用一個(gè)指針指向相關(guān)的 head page 的 page structure。關(guān)于 compound pages 的組織方式,請(qǐng)參見An introduction to compound pages。

          這種機(jī)制可以很容易從 tail page 的 page structure 找到整個(gè) compound page 的 head page。內(nèi)核中的許多接口都利用了這一特性,但它帶來一個(gè)歧義問題:如果某個(gè)函數(shù)收到參數(shù)是一個(gè)指向了 tail page 的 page structure,那么這個(gè)函數(shù)是應(yīng)該針對(duì)這個(gè) tail page 上執(zhí)行、還是在整個(gè) compound page 上執(zhí)行?或者,正如 Wilcox 在 12 月對(duì) folio 系列 patch 的第一封郵件中所說的:

          一個(gè)有 struct page 參數(shù)的函數(shù)通常預(yù)期收到的是一個(gè) head page 或者 base page,如果給它一個(gè) tail page 的話它就會(huì)出現(xiàn) BUG。有的函數(shù)也許對(duì)任何 page 都可以支持,直接操作 PAGE_SIZE 這么多字節(jié);有的函數(shù)可能針對(duì) head page 會(huì)操作 page_size()這么多字節(jié),而對(duì) base page 或者 tail page 則操作 PAGE_SIZE 這么多字節(jié);還有的可能收到 head page 或者 tail page 的時(shí)候都是按照 page_size()字節(jié)數(shù)來處理。我們現(xiàn)在的代碼中以上情況都有出現(xiàn)。

          (PAGE_SIZE 是一個(gè) base page 的 size,而 page_size()則返回一個(gè) page 的整體大小(它可能是個(gè) compound page)。這個(gè)特殊的 API 似乎在歷史上并沒有出現(xiàn)過很多 bug,但是作為一個(gè)定義得這么含糊的接口,遲早會(huì)引發(fā)問題。

          為了讓這種情況的處理更加明晰,Wilcox 提出了 "page folio" 的概念,它實(shí)際上仍然是一個(gè) page structure,只是保證了它一定不是 tail page。任何接受 folio page 參數(shù)的函數(shù)都會(huì)是對(duì)整個(gè) compound page 進(jìn)行操作(如果傳入的確實(shí)是一個(gè) compound page 的話),這樣就不會(huì)有任何歧義。從而可以使內(nèi)核里的內(nèi)存管理子系統(tǒng)更加清晰;也就是說,如果某個(gè)函數(shù)被改為只接受 folio page 作為參數(shù)的話,很明確,它們不適用于對(duì) tail page 的操作。

          當(dāng) Wilcox 第一次發(fā)布這一組 patch 時(shí),他強(qiáng)調(diào)的是這個(gè)改動(dòng)會(huì)帶來的另一個(gè)好處:任何函數(shù),如果它必須要對(duì)整個(gè) compound page 操作,但是卻傳入的只是一個(gè) tail page,都必須將指向 tail page 結(jié)構(gòu)的指針改為指向 head page 的指針。這通常是通過調(diào)用這個(gè)函數(shù)來實(shí)現(xiàn)的:

          struct page *compound_head(struct page *page);

          這個(gè)函數(shù)相對(duì)來說耗時(shí)很少,但是在對(duì)頁面進(jìn)行一次操作的過程中可能會(huì)被調(diào)用多次。這使得內(nèi)核變大了(因?yàn)樗且粋€(gè) inline 函數(shù)),并且也變慢了。一個(gè)接受 folio page 參數(shù)的函數(shù)就知道它收到的不會(huì)是 tail page,因此不需要調(diào)用 compound_head()。這樣既節(jié)省了時(shí)間又節(jié)省了內(nèi)存。

          folio 類型本身被定義為一個(gè)簡(jiǎn)單的封裝結(jié)構(gòu):

          struct folio {
          struct page page;
          };

          根據(jù)這個(gè)結(jié)構(gòu),建立起一套新的基礎(chǔ)設(shè)施。例如,get_folio()和 put_folio() 函數(shù)就跟 get_page()和 put_page() 函數(shù)一樣,用來管理對(duì) folio page 的引用,但不需要再調(diào)用 current_head()。此外還有一整套更高級(jí)的函數(shù)。其實(shí)這里真正耗費(fèi)時(shí)間的工作是將各個(gè)內(nèi)核子系統(tǒng)中的 API 轉(zhuǎn)換為使用新的類型;Wilcox 并沒有對(duì)這項(xiàng)工作的性質(zhì)進(jìn)行美化:

          這里會(huì)是大量的繁重工作,并且都是破壞性的。包括修改每一個(gè)文件系統(tǒng),以及許多設(shè)備驅(qū)動(dòng)程序!不過我覺得這個(gè)工作是值得的。

          到 3 月 5 日發(fā)布這組 patch 的第四個(gè)版本時(shí),核心 patch 和轉(zhuǎn)換 API 的 patch(Wilcox 沒有發(fā)布出來)加起來大約有 100 個(gè) commit,對(duì)于 review 來說,工作量已經(jīng)非常大了。

          也許是由于 patch 太大了,之前的郵件并沒有引起許多討論。不過針對(duì)最新的一版,Andrew Morton 看了一下,感到很擔(dān)心:

          天啊,這些改動(dòng)真是太繁雜了。我們需要記住更多的東西,今后我們將永遠(yuǎn)有一個(gè) "page "和 "folio "的混搭,到處都是從一個(gè)轉(zhuǎn)換到另一個(gè)的代碼。不斷地增加 folio 訪問代碼以及操作代碼來覆蓋現(xiàn)有的 page 訪問代碼和操作代碼,等等。

          我不清楚這一切是否真的值得。

          Hugh Dickins,也表示對(duì)這項(xiàng)工作缺乏興趣。另一方面,Kirill Shutemov 和 Michal Hocko 都表示支持,至少在概念上支持。Dave Chinner 說,對(duì)于文件系統(tǒng)開發(fā)者來說,"這種抽象是絕對(duì)必要的",尤其是當(dāng) page cache 今后能夠管理多種不同大小的 compound page 的時(shí)候。

          所以,換句話說,對(duì)于這項(xiàng)工作是否能改善內(nèi)核,目前核心開發(fā)者之間還沒有達(dá)成共識(shí)。隨著時(shí)間的推移,情況可能會(huì)發(fā)生變化,因?yàn)闀?huì)有更多的人關(guān)注它,它的優(yōu)勢(shì)(或缺乏優(yōu)勢(shì))將變得更加明顯。但一般來說,在內(nèi)存管理子系統(tǒng)中,變化往往是緩慢發(fā)生的,哪怕不是這么巨大、雜亂的改動(dòng)也是慢慢進(jìn)行的。還要注意的是命名的問題,很明顯,"folio" 并不受歡迎,盡管目前還沒有什么更合適的名字。因此,至少有一個(gè)結(jié)論是明確的:內(nèi)核很可能會(huì)有類似 folio 這樣的東西,但似乎不太可能很快發(fā)生。

          全文完
          LWN 文章遵循 CC BY-SA 4.0 許可協(xié)議。

          歡迎分享、轉(zhuǎn)載及基于現(xiàn)有協(xié)議再創(chuàng)作~

          長(zhǎng)按下面二維碼關(guān)注,關(guān)注 LWN 深度文章以及開源社區(qū)的各種新近言論~



          瀏覽 52
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  操操综合网| 三级做爱网站 | 69性爱视频 | 中文字幕av久久波多野结 | 欧美网站在线播放 |