最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

一文帶你實(shí)現(xiàn)完全解析HugePages(大內(nèi)存頁(yè))(趕快學(xué)習(xí)起來(lái)~)

2022-05-26 14:16 作者:補(bǔ)給站Linux內(nèi)核  | 我要投稿
  • 我們來(lái)分析一下 Linux 內(nèi)核是怎么實(shí)現(xiàn) HugePages 分配的。

本文使用 Linux 內(nèi)核 2.6.23 版本

HugePages分配器初始化

  • 在內(nèi)核初始化時(shí),會(huì)調(diào)用 hugetlb_init 函數(shù)對(duì) HugePages 分配器進(jìn)行初始化,其實(shí)現(xiàn)如下:

  • hugetlb_init 函數(shù)主要完成兩個(gè)工作:

  1. 初始化空閑大內(nèi)存頁(yè)鏈表 hugepage_freelists,這個(gè)鏈表保存了系統(tǒng)中能夠使用的大內(nèi)存。

  2. 為系統(tǒng)申請(qǐng)空閑的大內(nèi)存頁(yè),并且保存到 hugepage_freelists 鏈表中。

  • 我們?cè)賮?lái)分析下 alloc_fresh_huge_page 函數(shù)是怎么申請(qǐng)大內(nèi)存頁(yè)的,其實(shí)現(xiàn)如下:

  • 所以,alloc_fresh_huge_page 函數(shù)主要完成三個(gè)工作:

  1. 調(diào)用 alloc_pages_node 函數(shù)申請(qǐng)一個(gè)大內(nèi)存頁(yè)(2MB)。

  2. 設(shè)置大內(nèi)存頁(yè)的釋放回調(diào)函數(shù)為 free_huge_page,當(dāng)釋放大內(nèi)存頁(yè)時(shí),將會(huì)調(diào)用這個(gè)函數(shù)進(jìn)行釋放操作。

  3. 調(diào)用 put_page 函數(shù)釋放大內(nèi)存頁(yè),其將會(huì)調(diào)用 free_huge_page 函數(shù)進(jìn)行相關(guān)操作。

  • 那么,我們來(lái)看看 free_huge_page 函數(shù)是怎么釋放大內(nèi)存頁(yè)的,其實(shí)現(xiàn)如下:

free_huge_page 函數(shù)主要調(diào)用 enqueue_huge_page 函數(shù)把大內(nèi)存頁(yè)添加到空閑大內(nèi)存頁(yè)鏈表中,其實(shí)現(xiàn)如下:

  • 從上面的實(shí)現(xiàn)可知,enqueue_huge_page 函數(shù)只是簡(jiǎn)單的把大內(nèi)存頁(yè)添加到空閑鏈表 hugepage_freelists 中,并且增加計(jì)數(shù)器。

  • 假如我們?cè)O(shè)置了系統(tǒng)能夠使用的大內(nèi)存頁(yè)為 100 個(gè),那么空閑大內(nèi)存頁(yè)鏈表 hugepage_freelists 的結(jié)構(gòu)如下圖所示:


【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【891587639】整理了一些個(gè)人覺(jué)得比較好的學(xué)習(xí)書(shū)籍、視頻資料共享在群文件里面,有需要的可以自行添加哦!?。∏?00名進(jìn)群領(lǐng)取,額外贈(zèng)送一份價(jià)值699的內(nèi)核資料包(含視頻教程、電子書(shū)、實(shí)戰(zhàn)項(xiàng)目及代碼)? ??

?

  • 所以,HugePages 分配器初始化的調(diào)用鏈為:

  • hugetlbfs 文件系統(tǒng)

  • 為系統(tǒng)準(zhǔn)備好空閑的大內(nèi)存頁(yè)后,現(xiàn)在來(lái)了解下怎樣分配大內(nèi)存頁(yè)。在《一文讀懂 HugePages的原理》一文中介紹過(guò),要申請(qǐng)大內(nèi)存頁(yè),必須使用 mmap 系統(tǒng)調(diào)用把虛擬內(nèi)存映射到 hugetlbfs 文件系統(tǒng)中的文件中。

  • 免去繁瑣的文件系統(tǒng)掛載過(guò)程,我們主要來(lái)看看當(dāng)使用 mmap 系統(tǒng)調(diào)用把虛擬內(nèi)存映射到 hugetlbfs 文件系統(tǒng)的文件時(shí)會(huì)發(fā)生什么事情。

  • 每個(gè)文件描述符對(duì)象都有個(gè) mmap 的方法,此方法會(huì)在調(diào)用 mmap 函數(shù)映射到文件時(shí)被觸發(fā),我們來(lái)看看 hugetlbfs 文件的 mmap 方法所對(duì)應(yīng)的真實(shí)函數(shù),如下:

  • 從上面的代碼可以發(fā)現(xiàn),hugetlbfs 文件的 mmap 方法被設(shè)置為 hugetlbfs_file_mmap 函數(shù)。所以當(dāng)調(diào)用 mmap 函數(shù)映射 hugetlbfs 文件時(shí),將會(huì)調(diào)用 hugetlbfs_file_mmap 函數(shù)來(lái)處理。

  • 而 hugetlbfs_file_mmap 函數(shù)最主要的工作就是把虛擬內(nèi)存分區(qū)對(duì)象的 vm_flags 字段添加 VM_HUGETLB 標(biāo)志位,如下代碼:

  • 為虛擬內(nèi)存分區(qū)對(duì)象設(shè)置 VM_HUGETLB 標(biāo)志位的作用是:當(dāng)對(duì)虛擬內(nèi)存分區(qū)進(jìn)行物理內(nèi)存映射時(shí),會(huì)進(jìn)行特殊的處理,下面將會(huì)介紹。

虛擬內(nèi)存與物理內(nèi)存映射

  • 使用 mmap 函數(shù)映射到 hugetlbfs 文件后,會(huì)返回一個(gè)虛擬內(nèi)存地址。當(dāng)對(duì)這個(gè)虛擬內(nèi)存地址進(jìn)行訪問(wèn)(讀寫(xiě))時(shí),由于此虛擬內(nèi)存地址還沒(méi)有與物理內(nèi)存地址進(jìn)行映射,將會(huì)觸發(fā) 缺頁(yè)異常,內(nèi)核會(huì)調(diào)用 do_page_fault 函數(shù)對(duì) 缺頁(yè)異常 進(jìn)行修復(fù)。

  • 我們來(lái)看看整個(gè)流程,如下圖所示:

  • 所以,最終會(huì)調(diào)用 do_page_fault 函數(shù)對(duì) 缺頁(yè)異常 進(jìn)行修復(fù)操作,我們來(lái)看看 do_page_fault 做了什么工作,實(shí)現(xiàn)如下:

  • 上面代碼對(duì) do_page_fault 進(jìn)行了精簡(jiǎn),精簡(jiǎn)后主要完成4個(gè)工作:

  • 獲取當(dāng)前進(jìn)程對(duì)應(yīng)的內(nèi)存管理對(duì)象。

  • 調(diào)用 read_cr2 獲取觸發(fā)缺頁(yè)異常的虛擬內(nèi)存地址。

  • 通過(guò)觸發(fā) 缺頁(yè)異常 的虛擬內(nèi)存地址獲取對(duì)應(yīng)的虛擬內(nèi)存分區(qū)對(duì)象。

  • 調(diào)用 handle_mm_fault 函數(shù)對(duì) 缺頁(yè)異常 進(jìn)行修復(fù)。

  • 我們繼續(xù)來(lái)看看 handle_mm_fault 函數(shù)的實(shí)現(xiàn),代碼如下:


  • 對(duì) handle_mm_fault 函數(shù)進(jìn)行精簡(jiǎn)后,邏輯就非常清晰。如果虛擬內(nèi)存分區(qū)使用 HugePages,那么就調(diào)用 hugetlb_fault 函數(shù)進(jìn)行處理(由于我們分析使用 HugePages 的情況,所以剛好進(jìn)入這個(gè)分支)。

  • hugetlb_fault 函數(shù)主要對(duì)進(jìn)程的頁(yè)表進(jìn)行填充,所以我們先來(lái)回顧一下 HugePages 對(duì)應(yīng)的頁(yè)表結(jié)構(gòu),如下圖:

  • 從上圖可以看出,使用 HugePages 后,頁(yè)中間目錄 直接指向物理內(nèi)存頁(yè)。所以,hugetlb_fault 函數(shù)主要就是對(duì) 頁(yè)中間目錄項(xiàng) 進(jìn)行填充。實(shí)現(xiàn)如下:

  • 對(duì) hugetlb_fault 函數(shù)進(jìn)行精簡(jiǎn)后,主要完成兩個(gè)工作:

  1. 通過(guò)觸發(fā) 缺頁(yè)異常 的虛擬內(nèi)存地址找到其對(duì)應(yīng)的 頁(yè)中間目錄項(xiàng)。

  2. 調(diào)用 hugetlb_no_page 函數(shù)對(duì) 頁(yè)中間目錄項(xiàng) 進(jìn)行映射操作。

  • 我們?cè)賮?lái)看看 hugetlb_no_page 函數(shù)怎么對(duì) 頁(yè)中間目錄項(xiàng) 進(jìn)行填充:

  • 通過(guò)對(duì) hugetlb_no_page 函數(shù)進(jìn)行精簡(jiǎn)后,主要完成3個(gè)工作:

  1. 調(diào)用 alloc_huge_page 函數(shù)從空閑大內(nèi)存頁(yè)鏈表 hugepage_freelists 中申請(qǐng)一個(gè)大內(nèi)存頁(yè)。

  2. 通過(guò)大內(nèi)存頁(yè)的物理地址生成頁(yè)中間目錄項(xiàng)的值。

  3. 設(shè)置頁(yè)中間目錄項(xiàng)的值為上面生成的值。

  • 至此,HugePages 的映射過(guò)程已經(jīng)完成。

還有個(gè)問(wèn)題,就是 CPU 怎么知道 頁(yè)中間表項(xiàng) 指向的是 頁(yè)表 還是 大內(nèi)存頁(yè) 呢? 這是因?yàn)??頁(yè)中間表項(xiàng) 有個(gè) PSE 的標(biāo)志位,如果將其設(shè)置為1,那么就表明其指向 大內(nèi)存頁(yè) ,否則就指向 頁(yè)表。

總結(jié)

  • 本文介紹了 HugePages 實(shí)現(xiàn)的整個(gè)流程,當(dāng)然本文也只是介紹了申請(qǐng)內(nèi)存的流程,釋放內(nèi)存的流程并沒(méi)有分析,如果有興趣的話(huà)可以自己查閱源碼。



一文帶你實(shí)現(xiàn)完全解析HugePages(大內(nèi)存頁(yè))(趕快學(xué)習(xí)起來(lái)~)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
和林格尔县| 秦安县| 安康市| 绥化市| 江陵县| 韶山市| 延津县| 东乡| 梅州市| 合川市| 眉山市| 运城市| 通化县| 任丘市| 潍坊市| 蒙山县| 青冈县| 仁怀市| 定州市| 保山市| 通海县| 兴山县| 深圳市| 景宁| 高碑店市| 舟曲县| 会泽县| 陆良县| 辰溪县| 大宁县| 缙云县| 玛曲县| 泗阳县| 乡宁县| 依兰县| 五常市| 观塘区| 吉木乃县| 莱芜市| 江永县| 广昌县|