Linux Mem -- Slub內存分配器的幾點疑問及解答

目錄

1?? 怎樣通過object地址獲取其對應的struct slab?

2?? struct page、struct folio和struct slab類型之間轉換,怎么保證內部關鍵數據的傳遞?

3?? 怎樣判斷一個內存空間是屬于slab、page管理?

4?? struct page 結構中 __mapcount 和 page_type的理解


?

????????近期在解讀Linux slub內存分配管理器相關代碼,隨著代碼的不斷深入會不斷地自我提出新的疑問點,自己帶著疑問又再次走查代碼解答自我的疑問。這篇便是對于解讀Slub內存時的自我疑問解。

????????參考代碼:Linux-6.10

1?? 怎樣通過object地址獲取其對應的struct slab?

??????? 代碼中有 slab =folio_slab(fvirt_to_folio(object)) 邏輯,也就是通過object獲取其在內存中對應的page結構,在把page結構轉換為folio結構,最后將folio結構轉化為slab結構。也就該object對應的page結構空間,也是slab結構所在的空間。

?????? 通過slab分配邏輯也可有得出此結論。slab分配函數alloc_slab_page調用alloc_pages_node函數分配slab空間,alloc_pages_node函數返回值為分配空間對應的page結構(其實是通過獲取可用的page結構來確定可用內存),將獲取的struct page結構轉換為struct folio,再通過folio_slab()將folio轉換為struct slab,所以slab結構的空間就是page結構空間。

2?? struct page、struct folio和struct slab類型之間轉換,怎么保證內部關鍵數據的傳遞?

???????? 三個結構不僅共用內存空間,而且結構中部分關鍵元素在各自結構中偏移量也相同。如下系統編譯時,會計算部分關鍵元素在struct slab、struct folio的偏移量,將此偏移量和strcut page結構中關鍵元素的偏移量進行對比。

????????struct slab中 __page_flags 、__page_refcount 和struct page中的flags、_refcount 偏移量進行對比。

文件路徑:mm/slab.h//static_asserts 編譯靜態判斷函數,如果條件不滿足則編譯報錯。
#define SLAB_MATCH(pg, sl)                                                \
static_assert(offsetof(struct page, pg) == offsetof(struct slab, sl))   //在編譯過程判定flag在strcut page中偏移量是否和__page_flags 元素在struct slab中的偏移量是否一致,如果不一致則編譯報錯。
SLAB_MATCH(flags, __page_flags);    //判定_refcount在struct page中的偏移量是否和 __page_refcount在struct page中偏移量相同
SLAB_MATCH(_refcount, __page_refcount);   

????????struct folio中flags、_mapcount、refcount和struct page中flags、_mapcount、_refcount元素偏移量對比。

文件路徑:include/linux/mm_type.h#define FOLIO_MATCH(pg, fl)                                                \
static_assert(offsetof(struct page, pg) == offsetof(struct folio, fl))FOLIO_MATCH(flags, flags);
FOLIO_MATCH(_mapcount, _mapcount);
FOLIO_MATCH(_refcount, _refcount);

????????如果關鍵元素的偏移量不一致,則在編譯過程直接報錯。如果一致時,無論結構怎么轉換在不重新賦值給關鍵元素時,關鍵元素在各結構中值一致。例如將page結構轉換為slab結構、在不覆蓋flags元素空間時,page->flags 和 slab->_page_flags值相同。如此變保證了關鍵元素值在不同結構間的傳遞。

3?? 怎樣判斷一個內存空間是屬于slab、page管理?

?????? 上一節中可以推斷出Linux內核中struct slab、和 struct folio、strcut page存在共用空間情況,哪怎樣確認這個空間是屬于哪個結構?或者任意一內存地址空間是屬于slab還是page buddy內存管理器?

????? 內核提供一個判斷函數 static inline bool PageSlab(const struct page *page),該函數展開后如下:

static inline bool PageSlab(const struct page *page)
{struct folio = page_folio(page);return ((folio->page.page_type & (PAGE_TYPE_BASE | PG_slab)) == PAGE_TYPE_BASE);
}

從邏輯看當pag_type中不存在PG_slab標識時,則page屬于slab結構。有些反常規,常規情況會認為需要page_type中有PG_slab對應標識時才會認為該pag屬于slab結構。通過代碼進一步確認page_type變量來歷,沒有發現太多關于page_type賦值和初始化地方。但是通過struct page結構(如下),_mapcount 和 page_type共用4字節儲存單元,故對于_mapcount賦值則等同于操作pagetype。

Struct page {…union {                /* This union is 4 bytes in size. *//** If the page can be mapped to userspace, encodes the number* of times this page is referenced by a page table.*/atomic_t _mapcount;/** If the page is neither PageSlab nor mappable to userspace,* the value stored here may help determine what this page* is used for.  See page-flags.h for a list of page types* which are currently stored here.*/unsigned int page_type;};
…}

????? 從__init_single_page - >page_mapcount_reset函數可以獲取_mapcount = -1 即0xFFFF FFFF,則page_type 初始值也等于0xFFFF FFFF。如果該page要給slab用,則需要將PG_slab設置到page_type ,設置后page_type值為 0xFFFF EFFFF。當page已經為slab結構時,再去通過PageSlab()函數值進行類型判斷其結果為true,則表明了此結構為slab結構,該結構對應的內存空間由slab分配器進行管理。page buddy及其他類型的判斷也同此邏輯。

static inline void page_mapcount_reset(struct page *page)
{atomic_set(&(page)->_mapcount, -1);}

????????當從page buddy獲取到page給slab時,會調用__folio_set_slab函數對page.page_type進行PG_slab標識,表示該空間對應的slab結構,該空間由slab分配器進行管理。

slab page分配函數調用:alloc_slab_page -> __folio_set_slab

4?? struct page 結構中 __mapcount 和 page_type的理解

???????? 前文提到在struct page結構中_mapcount 和 page_type 共用4字節內存單元(同一union單元),初始化值相同為0xFFFF FFFF (-1,見page_mapcount_reset函數)。_mapcount代表該內存空間被映射用戶空間的引用次數(一個物理page內存可能被映射到不同用戶內存空間),page_type表示該page的類型即屬于buddy、slab、table等內存管理器或者頁表專用。實際使用該空間只能有個意義:要么表示用戶空間引用次數、要么標識page類型。具體表示什么意義可根據該空間值的范圍確認: 0xFFFF FFFF - 0xFFFF FF80 (PAGE_MAPCOUNT_RESERVE = -128 ?=0xFFFF FFF80)時表示該page被映射到用戶空間的次數,當小于PAGE_MAPCOUNT_RE-SERVE(0xFFFF FF80)時表示該page的類型

如下兩個函數可以佐證如上邏輯:

?A.page_type_has_type函數用于判定是否有page的類型,當base_type小于 PAGE_MAPCOUN-T_RESERVE(0xFFFF FF80)是被認為有page類型。

static inline int page_type_has_type(unsigned int page_type)
{return (int)page_type < PAGE_MAPCOUNT_RESERVE;}

B.page_mapcount函數獲取page的到用戶空間映射的應用次數,當mapcount小于PAGE_MAP-COUNT_RESERVE(0xFFFF FF80)時返回0被認為沒有引用,也就是該空間被設置了Page類型(enum pagetype)。

static inline int page_mapcount(struct page *page)
{int mapcount = atomic_read(&page->_mapcount) + 1;/* Handle page_has_type() pages */if (mapcount < PAGE_MAPCOUNT_RESERVE + 1)mapcount = 0;if (unlikely(PageCompound(page)))mapcount += folio_entire_mapcount(page_folio(page));return mapcount;
}

??????? 帶著疑問走讀代碼總會有不一樣的收貨,知道自己的理解依然不夠全面、甚至有誤但帶著問題前行會讓前行更有目的,也讓自己更多注重對于細節的理解。

??????? 繼續前行,日拱一卒!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/899490.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/899490.shtml
英文地址,請注明出處:http://en.pswp.cn/news/899490.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

pip install cryptacular卡住,卡在downloading階段

筆者安裝pip install cryptacular卡在downloading階段&#xff0c;但不知道為何 Collecting cryptacularCreated temporary directory: /tmp/pip-unpack-qfbl8f08http://10.170.22.41:8082 "GET http://repo.huaweicloud.com/repository/pypi/packages/42/69/34d478310d6…

Lag-Llama時間序列模型簡單實現數據預測

前言&#xff1a; 最近在大模型預測&#xff0c;簡單了解了lag-llama開源項目&#xff0c;網上也有很多講解原理的&#xff0c;這里就將如何快速上手使用說一下&#xff0c;只懂得一點點皮毛&#xff0c;有錯誤的地方歡迎大佬指出。 簡單介紹&#xff1a; Lag-Llama 是一個開…

Plastiform復制膠泥:高精度表面復制與測量的高效工具

在工業制造和質量檢測領域&#xff0c;表面復制和測量是確保產品質量的關鍵環節。Plastiform復制膠泥作為一種創新材料&#xff0c;憑借其出色的性能和多樣化的應用&#xff0c;為用戶提供了可靠的解決方案。它能夠快速捕捉復雜表面的細節&#xff0c;確保測量結果的準確性&…

AI大模型、機器學習以及AI Agent開源社區和博客

以下梳理了適合學習 AI大模型、機器學習、AI Agent和多模態技術 的英文網站、社區、官網和博客&#xff0c;按類別分類整理&#xff1a; 一、官方網站與開源平臺 1. AI大模型 (Large Language Models) ? OpenAI ? 官網: openai.com ? 內容: GPT系列模型文檔、研究論文、AP…

python 上下文管理器with

with 上下文管理器 上下文管理器示例如下&#xff1a;若想不使用with關鍵字 上下文管理器 任何實現了 enter() 和 exit() 方法的對象都可稱之為上下文管理器&#xff0c;上下文管理器對象可以使用 with 關鍵字。 必須同時具有__enter__和__exit__&#xff0c;就可以使用with語句…

買賣股票的最佳時機(121)

121. 買賣股票的最佳時機 - 力扣&#xff08;LeetCode&#xff09; 解法&#xff1a; class Solution { public:int maxProfit(vector<int>& prices) {int cur_min prices[0];int max_profit 0;for (int i 1; i < prices.size(); i) {if (prices[i] > cur…

CesiumJS 本地數據瓦片加載南北兩極出現圓點問題

const imageryProvider new UrlTemplateImageryProvider({url: "/gisimg/{z}/{x}/{reverseY}.png",minimumLevel: 0,maximumLevel: 19})上面這段代碼是加載本地切片&#xff0c;但是有個致命問題就是會出現南北兩極顯示藍色圓點 解決方案&#xff1a; 加上這句話&am…

Linux編譯器gcc/g++使用完全指南:從編譯原理到動靜態鏈接

一、gcc/g基礎認知 在Linux開發環境中&#xff0c;gcc和g是我們最常用的編譯器工具&#xff1a; gcc&#xff1a;GNU C Compiler&#xff0c;專門用于編譯C語言程序g&#xff1a;GNU C Compiler&#xff0c;用于編譯C程序&#xff08;也可編譯C語言&#xff09; &#x1f4cc…

Vue學習筆記集--computed

computed 在 Vue 3 的 Composition API 中&#xff0c;computed 用于定義響應式計算屬性 它的核心特性是自動追蹤依賴、緩存計算結果&#xff08;依賴未變化時不會重新計算&#xff09; 基本用法 1. 定義只讀計算屬性 import { ref, computed } from vue;const count ref(…

飛致云榮獲“Alibaba Cloud Linux最佳AI鏡像服務商”稱號

2025年3月24日&#xff0c;阿里云云市場聯合龍蜥社區發布“2024年度Alibaba Cloud Linux最佳AI鏡像服務商”評選結果。 經過主辦方的嚴格考量&#xff0c;飛致云&#xff08;即杭州飛致云信息科技有限公司&#xff09;憑借旗下MaxKB開源知識庫問答系統、1Panel開源面板、Halo開…

Vue如何利用Postman和Axios制作小米商城購物車----簡版

實現功能&#xff1a;全選、單選、購物數量顯示、合計價格顯示 實現效果如下&#xff1a; 思路&#xff1a; 1.數據要利用寫在Postman里面&#xff0c;通過地址來調用Postman里面的數據。 2.寫完數據后&#xff0c;給寫的數據一個名字&#xff0c;然后加上一個空數組&#xf…

第一篇:系統分析師首篇

目錄 一、目標二、計劃三、完成情況1.宏觀思維導圖2.過程中的團隊管理和其它方面的思考 四、意外之喜(最少2點)1.計劃內的明確認知和思想的提升標志2.計劃外的具體事情提升內容和標志 一、目標 通過參加考試&#xff0c;訓練學習能力&#xff0c;而非單純以拿證為目的。 1.在復…

CSS學習筆記4——盒子模型

目錄 盒子模型是什么&#xff1f; 盒子模型的組成 一、div標簽 二、邊框屬性 1、border-style:邊框樣式 2、border-width:邊框寬度 3、border-color:邊框顏色、border&#xff1a;綜合設置 4、border-radius:圓角邊框 5、border-image&#xff1a;圖像邊框 三、邊距屬性…

復現文獻中的三維重建圖像生成,包括訓練、推理和可視化

要復現《One - 2 - 3 - 45 Fast Single Image to 3D Objects with Consistent Multi - View Generation and 3D Diffusion (CVPR)2024》文獻中的三維重建圖像生成&#xff0c;包括訓練、推理和可視化&#xff0c;并且確保代碼能正常運行&#xff0c;下面是基本的實現步驟和示例…

stable diffusion 本地部署教程 2025最新版

前提&#xff1a; 需要環境 git git下載地址Git - Downloading Package ? 直接裝即可 python3.10.6 下載地址 Python Release Python 3.10.6 | Python.org ? 記得python環境一定要3.10.6&#xff01;&#xff01;&#xff01; 第一個版本 項目地址https://github.…

【二刷代碼隨想錄】螺旋矩陣求解方法、推薦習題

一、求解方法 &#xff08;1&#xff09;按點模擬路徑 在原有坐標的基準上&#xff0c;疊加 橫縱坐標 的變化值&#xff0c;求出下一位置&#xff0c;并按題完成要求。但需注意轉角的時機判斷&#xff0c;特別是最后即將返回上一出發點的位置。 &#xff08;2&#xff09;按層…

從Manus到OpenManus:AI智能體技術如何重塑未來生活場景?

從Manus到OpenManus&#xff1a;AI智能體技術如何重塑未來生活場景&#xff1f; 一、現狀&#xff1a;AI智能體技術面臨的三大核心矛盾 &#xff08;通過分析用戶高頻痛點與市場反饋提煉&#xff09; 能力與門檻的失衡 Manus展示的復雜任務處理能力&#xff08;如股票分析、代…

迭代器與可迭代對象

概念層面&#xff1a; 可迭代對象&#xff1a; 一個可迭代對象是指任何可以返回一個迭代器的對象。換句話說&#xff0c;它實現了 __iter__() 方法 比如&#xff1a;列表、元組、字典、字符串、集合等 直接通過 for 循環使用&#xff0c;因為 for 循環內部會調用其 __iter__(…

總結PostgreSQL創建數據庫失敗的解決辦法

作者&#xff1a;朱金燦 來源&#xff1a;clever101的專欄 系統環境是Windows 11 專業版&#xff0c;PostgreSQL版本是17。在運行sql語句創建數據庫時出現錯誤&#xff1a; 閿欒: template database \"template1\" has a collation version mismatch DETAIL: Th…

Mybatis源碼 插件機制

簡介 插件是一種常見的擴展方式&#xff0c;大多數開源框架也都支持用戶通過添加自定義插件的方式來擴展或者改變原有的功能&#xff0c;MyBatis中也提供的有插件&#xff0c;雖然叫插件&#xff0c;但是實際上是通過攔截器(Interceptor)實現的&#xff0c;在MyBatis的插件模塊…