国产精品久久久aaaa,日日干夜夜操天天插,亚洲乱熟女香蕉一区二区三区少妇,99精品国产高清一区二区三区,国产成人精品一区二区色戒,久久久国产精品成人免费,亚洲精品毛片久久久久,99久久婷婷国产综合精品电影,国产一区二区三区任你鲁

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

page struct的三種存放方式

Linux閱碼場 ? 來源:Linuxer ? 2020-08-03 16:33 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

隨著硬件能力的提升,系統內存容量變得越來越大。尤其是在服務器上,過T級別的內存容量也已經不罕見了。

如此海量內存給內核帶來了很多挑戰,其中之一就是page struct存放在哪里。

page struct的三種存放方式

在內核中,我們將物理內存按照頁大小進行管理。這樣每個頁就對應一個page struct作為這個頁的管理數據結構。

隨著內存容量的增加,相對應的page struct也就增加。而這部分內存和其他的內存略有不同,因為這部分內存不能給到頁分配器。也就是必須在系統能夠正常運行起來之前就分配好。

在內核中我們可以看到,為了應對這樣的變化進化出了幾個不同的版本。有幸的是,這部分內容我們現在還能在代碼中直接看到,因為這個實現是通過內核配置來區分的。我們通過查找_pfn_to_page的定義就能發現一下幾種memory model:

CONFIG_FLATMEM

CONFIG_SPARSEMEM

CONFIGSPARSEMEMVMEMMAP

接下來讓小編給各位看官一一道來。

1) FLATMEM

在這種情況下,宏_pfn_to_page的定義是:

#define__pfn_to_page(pfn)(mem_map+((pfn)-ARCH_PFN_OFFSET))

而這個mem_map的定義是

structpage*mem_map;

所以在這種情況下,page struct就是一個大數組,所有的人都按照自己的物理地址有序得挨著。

2) SPARSEMEM

雖然第一種方式非常簡單直觀,但是有幾個非常大的缺點:

內存如果有空洞,那么中間可能會有巨大的page struct空間浪費

所有的page struct內存都在一個NUMA節點上,會耗盡某一個節點內存,甚至是分配失敗

且會產生夸NUMA訪問導致性能下降

所以第二種方式就是將內存按照一定粒度,如128M,劃分了section,每個section中有個成員指定了對應的page struct的存儲空間。

這樣就解決了上述的幾個問題:

如果有空洞,那么對應的 page struct就不會占用空間

每個section對應的page struct是屬于本地NUMA的

怎么樣,是不是覺得很完美。這一部分具體的實現可以可以看函數sparse_init()函數。

有了這個基礎知識,我們再來看這種情況下_pfn_to_page的定義:

#define __pfn_to_page(pfn) ({ unsigned long __pfn = (pfn); struct mem_section *__sec = __pfn_to_section(__pfn); __section_mem_map_addr(__sec) + __pfn; })

就是先找到pfn對應的section,然后在section中保存的地址上翻譯出對應pfn的page struct。

既然講到了這里,我們就要對sparsemem中重要的組成部分mem_section多說兩句。

先來一張mem_section的整體圖解:

這是一個 NRSECTIONROOTS x SECTIONSPERROOT的二維數組。其中每一個成員就代表了我們剛才提到的128M內存。

當然最開始它不是這個樣子的。

其實最開始這個數組是一個靜態數組。很明顯這么做帶來的問題是這個數組定義太大太小都不合適。所以后來引進了CONFIGSPARSEMEMEXTREME編譯選項,當設置為y時,這個數組就變成了動態的。

如果上面這個算作是空間上的限制的話,那么接下來就是一個時間上的限制了。

在系統初始化時,每個mem_section都要和相應的內存空間關聯。在老版本上,這個步驟通過對整個數組接待完成。原來的版本上問題不大,因為整個數組的大小還沒有很大。但隨著內存容量的增加,這個數值就變得對系統有影響了。如果系統上確實有這么多內存,那么確實需要初始化也就忍了。但是在內存較小的系統上,哪怕沒有這么多內存,還是要挨個初始化,那就浪費了太多的時間。

commit c4e1be9ec1130fff4d691cdc0e0f9d666009f9aeAuthor: Dave Hansen Date: Thu Jul 6 15:36:44 2017 -0700 mm, sparsemem: break out of loops earl

Dave在這個提交中增加了對系統最大存在內存的跟蹤,來減少不必要的初始化時間。

瞧,內核代碼一開始其實也沒有這么高大上不是。

3) SPARSEMEM_VMEMMAP

最后要講的,也是當前x86系統默認配置的內存模型是SPARSEMEM_VMEMMAP。那為什么要引入這么一個新的模型呢?那自然是sparsemem依然有不足。

細心的朋友可能已經注意到了,前兩種內存模型在做pfn到page struct轉換是有著一些些的差異。為了看得清,我們把這兩個定義再拿過來對比一下:

先看看FLATMEM時的定義:

#define__pfn_to_page(pfn)(mem_map+((pfn)-ARCH_PFN_OFFSET))

再來看看使用SPASEMEM后的定義:

#define __pfn_to_page(pfn) ({ unsigned long __pfn = (pfn); struct mem_section *__sec = __pfn_to_section(__pfn); __section_mem_map_addr(__sec) + __pfn; })

更改后,需要先找到section,然后再從section->memmap的內容中換算出page的地址。

不僅計算的內容多了,更重要的是還有一次訪問內存的操作

可以想象,訪問內存和單純計算之間的速度差異那是巨大的差距。

既然產生了這樣的問題,那有沒有辦法解決呢?其實說來簡單,內核開發者利用了我們常見的一個內存單元來解決這個問題。

頁表

是不是很簡單粗暴?如果我們能夠通過某種方式將page struct線性映射到頁表,這樣我們不就能又通過簡單的計算來換算物理地址和page struct了么?

內核開發者就是這么做的,我們先來看一眼最后那簡潔的代碼:

#define__pfn_to_page(pfn)(vmemmap+(pfn))

經過內核開發這的努力,物理地址到page struct的轉換又變成如此的簡潔。不需要訪問內存,所以速度的問題得到了解決。

但是天下沒有免費的午餐,世界哪有這么美好,魚和熊掌可以兼得的情況或許只有在夢境之中。為了達到如此簡潔的轉化,我們是要付出代價的。為了實現速度上的提升,我們付出了空間的代價。

至此引出了計算機界一個經典的話題:

時間和空間的轉換

話不多說,也不矯情了,我們來看看內核中實現的流程。

既然是利用了頁表進行轉換,那么自然是要構建頁表在做這樣的映射。這個步驟主要由函數vmemmap_populate()來完成,其中還區分了有沒有大頁的情況。我們以普通頁的映射為例,看看這個實現。

int __meminit vmemmap_populate_basepages(unsigned long start, unsigned long end, int node){ unsigned long addr = start; pgd_t *pgd; p4d_t *p4d; pud_t *pud; pmd_t *pmd; pte_t *pte; for (; addr < end; addr += PAGE_SIZE) { pgd = vmemmap_pgd_populate(addr, node); if (!pgd) return -ENOMEM; p4d = vmemmap_p4d_populate(pgd, addr, node); if (!p4d) return -ENOMEM; pud = vmemmap_pud_populate(p4d, addr, node); if (!pud) return -ENOMEM; pmd = vmemmap_pmd_populate(pud, addr, node); if (!pmd) return -ENOMEM; pte = vmemmap_pte_populate(pmd, addr, node); if (!pte) return -ENOMEM; vmemmap_verify(pte, node, addr, addr + PAGE_SIZE); } return 0;}

內核代碼的優美之處就在于,你可能不一定看懂了所有細節,但是從優美的結構上能猜到究竟做了些什么。上面這段代碼的工作就是對每一個頁,按照層級去填充頁表內容。其中具體的細節就不在這里展開了,相信有興趣的同學會自行去探索。

那這么做的代價究竟是多少呢?

以x86為例,每個section是128M,那么每個section的page struct正好是2M,也就是一個大頁。

(128M / 4K) * 64 = (128 * (1 < 20) / (1 < 12)) * 64 = 2M

假如使用大頁做頁表映射,那么每64G才用掉一個4K頁表做映射。

128M * 512 = 64G

所以在使用大頁映射的情況下,這個損耗的級別在百萬分之一。還是能夠容忍的。

好了,我們終于沿著內核發展的歷史重走了一遍安放page struct之路。相信大家在這一路上領略了代碼演進的樂趣,也會對以后自己代碼的設計有了更深的思考。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 服務器
    +關注

    關注

    13

    文章

    10117

    瀏覽量

    91033
  • 數據結構
    +關注

    關注

    3

    文章

    573

    瀏覽量

    41418
  • PAGE
    +關注

    關注

    0

    文章

    11

    瀏覽量

    20523

原文標題:page結構體,何處安放你的靈魂?

文章出處:【微信號:LinuxDev,微信公眾號:Linux閱碼場】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    伺服電機的三種制動方式有什么區別?

    伺服電機作為自動化控制系統中執行元件的核心部件,其制動性能直接影響設備的定位精度和安全可靠性。目前主流的伺服電機制動方式包括動態制動、再生制動和電磁機械制動三種,它們在制動原理、應用場景及技術特點上
    的頭像 發表于 09-19 18:26 ?1217次閱讀
    伺服電機的<b class='flag-5'>三種</b>制動<b class='flag-5'>方式</b>有什么區別?

    MEMS中的三種測溫方式

    在集成MEMS芯片的環境溫度測量領域,熱阻、熱電堆和PN結原理是三種主流技術。熱阻是利用熱敏電阻,如金屬鉑或注入硅的溫度電阻系數恒定,即電阻隨溫度線性變化的特性測溫,電阻變化直接對應絕對溫度,需恒流源供電。
    的頭像 發表于 07-16 13:58 ?1351次閱讀
    MEMS中的<b class='flag-5'>三種</b>測溫<b class='flag-5'>方式</b>

    1553B總線常見三種組網方式

    1553B總線作為航空電子系統中的關鍵通信協議,其組網方式直接影響系統的可靠性和實時性。本文將深入解析1553B總線的三種典型組網結構:單總線結構、雙冗余總線和多總線分層架構,并結合實際應用場景分析
    的頭像 發表于 06-21 17:39 ?1408次閱讀
    1553B總線常見<b class='flag-5'>三種</b>組網<b class='flag-5'>方式</b>

    開關電源三種控制模式:PWM/PFM/PSM

    摘要 本文詳細介紹了開關電源的三種主要調制方式:PWM(脈沖寬度調制)、PFM(脈沖頻率調制)和PSM(脈沖跨周期調制)。PWM通過調整脈沖寬度保持恒定頻率,適用于重負載,但輕負載效率低。PFM則在
    發表于 06-09 16:11

    HarmonyOS基礎組件:Button三種類型的使用

    中的Button相較于Android原生來說,功能比較豐富,擴展性高,減少了開發者的代碼數量,簡化了使用方式。不僅可以自定義圓角還支持三種樣式。 常用屬性 名稱 參數類型 描述 type
    的頭像 發表于 06-09 15:48 ?2195次閱讀
    HarmonyOS基礎組件:Button<b class='flag-5'>三種</b>類型的使用

    介紹三種常見的MySQL高可用方案

    在生產環境中,為了確保數據庫系統的連續可用性、降低故障恢復時間以及實現業務的無縫切換,高可用(High Availability, HA)方案至關重要。本文將詳細介紹三種常見的 MySQL 高可用
    的頭像 發表于 05-28 17:16 ?1038次閱讀

    信號隔離器三種供電方式的區別

    信號隔離器是一重要的信號隔離裝置,其供電方式主要有獨立供電、回路供電和輸出回路供電三種。以下是這三種供電方式的詳細區別: 一、獨立供電 1
    的頭像 發表于 04-17 16:23 ?1140次閱讀
    信號隔離器<b class='flag-5'>三種</b>供電<b class='flag-5'>方式</b>的區別

    雙極型極管放大電路的三種基本組態的學習課件免費下載

      本文檔的主要內容詳細介紹的是雙極型極管放大電路的三種基本組態的學習課件免費下載包括了:共集電極放大電路,共基極放大電路,三種基本組態的比較   輸入信號ui 和輸出信號uo 的公共端是集電極。
    發表于 04-11 16:39 ?27次下載

    redis三種集群方案詳解

    在Redis中提供的集群方案總共有三種(一般一個redis節點不超過10G內存)。
    的頭像 發表于 03-31 10:46 ?1323次閱讀
    redis<b class='flag-5'>三種</b>集群方案詳解

    CMOS,Bipolar,FET這三種工藝的優缺點是什么?

    在我用photodiode工具選型I/V放大電路的時候,系統給我推薦了AD8655用于I/V,此芯片為CMOS工藝 但是查閱資料很多都是用FET工藝的芯片,所以請教下用于光電信號放大轉換(主要考慮信噪比和帶寬)一般我們用哪種工藝的芯片, CMOS,Bipolar,FET這三種工藝的優缺點是什么?
    發表于 03-25 06:23

    GaN、超級SI、SiC這三種MOS器件的用途區別

    如果想要說明白GaN、超級SI、SiC這三種MOS器件的用途區別,首先要做的是搞清楚這三種功率器件的特性,然后再根據材料特性分析具體應用。
    的頭像 發表于 03-14 18:05 ?2281次閱讀

    FOC中的三種電流采樣方式,你真的會選擇嗎?(可下載)

    的基礎,用一句話來形容就是“基礎不對,努力白費”,由此可見電流采樣在整 個 FOC 算法中的作用電流采樣的方式一般分為電阻、雙電阻、單電阻,這三種采樣方式都有其
    發表于 03-12 15:04 ?3次下載

    深入解析三種鋰電池封裝形狀背后的技術路線與工藝奧秘

    在新能源時代,鋰電池作為核心動力與儲能單元,其重要性不言而喻。而在鋰電池的諸多特性中,封裝形狀這一外在表現形式,實則蘊含著復雜的技術考量與工藝邏輯。方形、圓柱、軟包三種主流封裝形狀,各自對應著獨特
    的頭像 發表于 02-17 10:10 ?2108次閱讀
    深入解析<b class='flag-5'>三種</b>鋰電池封裝形狀背后的技術路線與工藝奧秘

    三種太赫茲波的產生方式

    本文簡單介紹了三種太赫茲波的產生方式。 太赫茲波(THz)是一電磁波,在電磁波譜上位于紅外與微波之間。太赫茲光子能量在1-10 meV范圍之間,在光譜分析、醫療成像、移動通信方面都有非常廣闊
    的頭像 發表于 02-17 09:09 ?3646次閱讀
    <b class='flag-5'>三種</b>太赫茲波的產生<b class='flag-5'>方式</b>

    示波器的三種觸發模式

    示波器的觸發方式不僅影響波形捕捉的時機,還決定了顯示的波形是否穩定。 常見的觸發模式有三種: 單次觸發 (Single)、 正常觸發 (Normal)和 自動觸發 (Auto)。下面將對這三種觸發
    的頭像 發表于 01-07 11:04 ?1.3w次閱讀
    示波器的<b class='flag-5'>三種</b>觸發模式