Linux 內核 Slab 分配器核心組件詳解

Slab 分配器是 Linux 內核中用于高效管理內存的機制,其核心目標是通過對象緩存減少內存碎片和分配/釋放開銷。以下詳細解析其核心組件及其協作關系:

?

一、Slab 系統的核心組件

?

組件 描述 作用場景

Slab 描述符 每個 Slab 的管理結構(如 struct slab),記錄頁幀狀態、空閑對象鏈表等。 跟蹤 Slab 的元數據(如對象數量、空閑鏈表頭、所屬緩存等)。

Slab 節點 NUMA 架構下的內存節點(struct kmem_cache_node),管理本地 Slab 資源。 優化 NUMA 系統內存訪問,減少跨節點訪問延遲。

本地對象緩沖池 每 CPU 的緩存(struct kmem_cache_cpu),存放快速分配的空閑對象。 無鎖快速分配對象,避免全局競爭。

共享對象緩沖池 節點級別的共享緩存池(struct kmem_cache_node 中的鏈表)。 當本地緩沖池耗盡時,從共享池批量獲取對象或 Slab。

三個 Slab 鏈表 每個節點維護三個鏈表:slabs_full、slabs_partial、slabs_free。 按 Slab 的填充狀態分類,優先從 slabs_partial 分配,釋放時調整鏈表位置。

N 個 Slab 物理連續的頁幀集合,劃分為多個等大小的對象。 承載實際對象存儲,一個 Slab 可分配多個對象。

Slab 緩存對象 每個 Slab 中劃分出的內存塊,用于存儲特定類型的內核對象(如 inode)。 直接被內核代碼分配和釋放,避免頻繁調用頁分配器。

?

二、組件協作流程

?

1. 對象分配流程

?

步驟 1:嘗試從 本地對象緩沖池(Per-CPU 緩存)獲取空閑對象。

步驟 2:若本地池為空,從 共享對象緩沖池(節點 slabs_partial 鏈表)批量獲取對象填充本地池。

步驟 3:若共享池耗盡,從 Slab 空閑鏈表(slabs_free)分配新 Slab,分割為對象后加入本地池。

步驟 4:若系統內存不足,觸發頁分配器(如 Buddy System)分配新頁幀創建 Slab。

?

2. 對象釋放流程

?

步驟 1:將對象歸還到 本地對象緩沖池。

步驟 2:若本地池已滿,將部分對象批量返還到 共享對象緩沖池(slabs_partial)。

步驟 3:若 Slab 中所有對象均釋放,將 Slab 移至 slabs_free 鏈表,在內存緊張時釋放回頁分配器。

三、關鍵數據結構關系

?

struct kmem_cache

├── struct kmem_cache_cpu *cpu_slab // 每 CPU 的本地緩存

├── struct kmem_cache_node *node[NUM_NODES] // NUMA 節點共享緩存

│ ├── struct list_head slabs_full // 滿 Slab 鏈表

│ ├── struct list_head slabs_partial // 部分滿 Slab 鏈表

│ └── struct list_head slabs_free // 空閑 Slab 鏈表

└── unsigned int object_size // 對象大小

?

struct slab

├── struct list_head slab_list // 所屬鏈表(full/partial/free)

├── void *freelist // 空閑對象鏈表頭

├── unsigned int active_objects // 已分配對象數

└── unsigned int num_pages // 占用的頁幀數

?

四、代碼案例分析:Slab 分配器的內部操作

?

以下偽代碼展示 Slab 分配器在對象分配時的核心邏輯:

?

// 分配對象

void *kmem_cache_alloc(struct kmem_cache *cache, gfp_t flags) {

? ? struct kmem_cache_cpu *cpu_slab = get_cpu_ptr(cache->cpu_slab);

? ? void *object;

?

? ? // 1. 嘗試從本地緩沖池獲取對象

? ? if (likely(cpu_slab->freelist)) {

? ? ? ? object = cpu_slab->freelist;

? ? ? ? cpu_slab->freelist = get_next_freepointer(object);

? ? ? ? return object;

? ? }

?

? ? // 2. 本地池為空,從節點共享池填充

? ? if (unlikely(!fill_local_cache(cpu_slab, cache, flags))) {

? ? ? ? // 3. 共享池不足,分配新 Slab

? ? ? ? struct slab *new_slab = allocate_slab(cache, flags);

? ? ? ? if (!new_slab)

? ? ? ? ? ? return NULL; // 內存不足

? ? ? ? cpu_slab->freelist = new_slab->freelist;

? ? ? ? cpu_slab->slab = new_slab;

? ? ? ? object = cpu_slab->freelist;

? ? ? ? cpu_slab->freelist = get_next_freepointer(object);

? ? ? ? return object;

? ? }

? ? // ... 其他錯誤處理

}

?

// 填充本地緩沖池

static int fill_local_cache(struct kmem_cache_cpu *cpu_slab,?

? ? ? ? ? ? ? ? ? ? ? ? ? ?struct kmem_cache *cache,?

? ? ? ? ? ? ? ? ? ? ? ? ? ?gfp_t flags) {

? ? struct kmem_cache_node *node = cache->node[cpu_to_node(smp_processor_id())];

? ? struct slab *slab;

?

? ? // 從節點的部分滿鏈表獲取 Slab

? ? spin_lock(&node->list_lock);

? ? slab = list_first_entry_or_null(&node->slabs_partial, struct slab, slab_list);

? ? if (!slab) {

? ? ? ? // 若無部分滿 Slab,嘗試從空閑鏈表分配

? ? ? ? slab = list_first_entry_or_null(&node->slabs_free, struct slab, slab_list);

? ? ? ? if (!slab) {

? ? ? ? ? ? spin_unlock(&node->list_lock);

? ? ? ? ? ? return 0; // 需要分配新 Slab

? ? ? ? }

? ? ? ? list_move(&slab->slab_list, &node->slabs_partial);

? ? }

? ? // 將 Slab 的空閑對象導入本地緩存

? ? cpu_slab->freelist = slab->freelist;

? ? slab->freelist = NULL;

? ? slab->active_objects = cache->num_objects;

? ? list_move(&slab->slab_list, &node->slabs_full);

? ? spin_unlock(&node->list_lock);

? ? cpu_slab->slab = slab;

? ? return 1;

}

?

五、關鍵設計優勢

?

減少內存碎片

Slab 按對象大小預分配內存塊,避免頻繁分割物理頁,減少外部碎片。

?

提升分配速度

通過本地緩沖池(Per-CPU 無鎖緩存)實現快速分配,避免全局鎖競爭。

?

NUMA 優化

每個節點管理本地 Slab,減少跨節點內存訪問帶來的性能損耗。

?

內存重用

釋放的對象歸還到空閑鏈表,避免頻繁調用頁分配器,降低系統開銷。

?

六、實際觀察工具

?

查看 Slab 狀態

?

cat /proc/slabinfo

輸出示例:顯示每個緩存的名稱、對象數量、活動對象數、Slab 使用情況等。

內核調試工具

使用 systemtap 或 ftrace 跟蹤特定緩存的對象分配/釋放路徑。

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

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

相關文章

Oracle 的AHF (Automatic Health Framework) 工具

Oracle 的AHF (Automatic Health Framework) 工具 Oracle AHF (Automatic Health Framework) 是 Oracle 官方提供的診斷工具集合,用于自動收集、分析和診斷 Oracle 數據庫及集群環境的健康狀態和問題。 一 AHF 核心功能概述 1. 主要組件 TFA (Trace File Analyz…

華為服務器obsutil使用方法

本文不生產技術,只做技術的搬運工!!! 前言 最近在使用華為云服務器進行模型訓練,發現其上傳下載文件都極慢,詢問華為官方人員是否限速,對方推薦使用obsutil作為中轉服務進行下載,在…

【大模型訓練】中短序列attention 和MOE層并行方式(二)

我們考慮一個典型的Transformer模型結構,在多層堆疊中,其中包含Attention層和MoE層(FeedForward層被替換為MoE層)。在模型最后是LM Head(語言模型頭),通常是一個全連接層,將隱層向量…

2025-06-09(批量智能裁剪視頻尺寸并延長視頻時長)

import os import subprocess import random import json # 配置參數 TARGET_WIDTH 500 TARGET_HEIGHT 600 TARGET_DURATION 180 # 目標時長(秒) OUTPUT_DIR "processed_videos" MIRROR_MODES ["none", "horizontal&quo…

CKA考試知識點分享(9)---gateway api

CKA 版本:1.32 第九套題是涉及gateway api相關。 注意:本文不是題目,只是為了學習相關知識點做的實驗。僅供參考 實驗目的 創建一個gateway api,來實現后端鏡像的外部訪問。 gateway api 通過nginx實現 實驗開始 安裝nginx ga…

Kafka 消息模式實戰:從簡單隊列到流處理(一)

一、Kafka 簡介 ** Kafka 是一種分布式的、基于發布 / 訂閱的消息系統,由 LinkedIn 公司開發,并于 2011 年開源,后來成為 Apache 基金會的頂級項目。它最初的設計目標是處理 LinkedIn 公司的海量數據,如用戶活動跟蹤、消息傳遞和…

Linux中使用yum安裝MYSQL

1、關系型數據庫 MySQL 使用 yum 安裝mysql 1、檢查是否已經安裝 Mysql rpm -qa | grep mysql如果安裝了 就進行卸載 rpm -e mysql-community-libs-5.7.44-1.el7.x86_64 rpm -e mysql57-community-release-el7-11.noarch rpm -e mysql-community-common-5.7.44-1.el7.x86_64…

Linux 文件系統與 I/O 編程核心原理及實踐筆記

文章目錄 一、理解文件1.1 狹義理解1.2 廣義理解1.3 文件操作的歸類認識1.4 系統角度:進程與文件的交互1.5 實踐示例 二、回顧 C 文件接口2.1 hello.c 打開文件2.2 hello.c 寫文件2.3 hello.c 讀文件2.4 輸出信息到顯示器的幾種方法2.5 stdin & stdout & st…

1.9 Express

Express 是一個基于 Node.js 平臺的輕量級、靈活的 Web 應用框架,它為構建 Web 應用和 API 提供了一系列強大的功能。 核心特性 中間件支持:Express 使用中間件(middleware)函數來處理 HTTP 請求和響應。中間件可以訪問請求對象&…

面壁智能MiniCPM4.0技術架構與應用場景

📋 目錄 1. 引言:端側智能新時代2. MiniCPM4.0概述3. 核心技術架構 3.1 高效雙頻換擋機制3.2 稀疏注意力機制3.3 系統級優化創新 4. 技術突破與性能表現5. 應用場景深度解析 5.1 智能手機應用5.2 智能家居場景5.3 汽車智能化5.4 其他端側應用 6. 行業影…

RabbitMQ路由核心解密:從Exchange到RoutingKey的深度實踐與避坑指南

🔍 RabbitMQ路由核心解密:從Exchange到RoutingKey的深度實踐與避坑指南 “消息去哪了?”——這是每位RabbitMQ使用者在調試時最常發出的靈魂拷問。 理解Exchange與RoutingKey的協作機制,正是解開路由謎題的關鍵鑰匙。 一、Exchang…

Spring MVC完全指南 - 從入門到精通

目錄 1. Spring MVC簡介 2. MVC架構模式 3. Spring MVC核心組件 4. 請求處理流程 5. 控制器詳解 6. 請求映射 7. 參數綁定 8. 數據驗證 9. 視圖解析器 10. 模型數據處理 11. 異常處理 12. 攔截器 13. 文件上傳下載 14. RESTful API 15. 配置詳解 總結 1. Sprin…

實戰使用docker compose 搭建 Redis 主從復制集群

文章目錄 前言技術積累1、Redis 主從復制機制2、Docker Compose 編排3、 Redis 配置文件定制4、 驗證主從狀態5、 自動化部署與維護 環境準備實戰演示創建redis目錄及配置1、創建redis目錄2、創建redis配置文件 啟動redis集群服務1、創建docker-compose編排文件2、編排docker-c…

【學習筆記】RTSP-Ovnif-GB28181

【學習筆記】RTSP-Ovnif-GB28181 一、RTSP_RTP_RTCP RTSP(Real Time Streaming Protocol),RFC2326,實時流傳輸協議,是TCP/IP協議體系中的一個應用層協議。 RTP協議詳細說明了在互聯網上傳遞音頻和視頻的標準數據包格…

stm32-c8t6實現語音識別(LD3320)

目錄 LD3320介紹: 功能引腳 主要特色功能 通信協議 端口信息 開發流程 stm32c8t6代碼 LD3320驅動代碼: LD3320介紹: 內置單聲道mono 16-bit A/D 模數轉換內置雙聲道stereo 16-bit D/A 數模轉換內置 20mW 雙聲道耳機放大器輸出內置 5…

RAG技術全解析:從概念到實踐,構建高效語義檢索系統——嵌入模型與向量數據庫搭建指南

一、RAG技術概述:為什么需要RAG? 1.1 什么是RAG? RAG(Retrieval-Augmented Generation)是一種結合檢索與生成能力的AI架構。其核心思想是通過外部知識庫動態增強大語言模型(LLM)的生成能力&…

【資源分享】手機玩轉經典游戲!小雞模擬器1.9.0:PSP/NDS/GBA完美運行!

阿燦今天給大家推薦一款小雞模擬器,這是一個老款PC和掌上游戲機模擬器。完美模擬街機(fbamamemameplus).PS、PSP、FC(NES)SFC(SNES)、GBA、GBC、MD、NDS、DC、NGP、WS (WSC) PCE、ONS 等18款經典掌機游戲機。小雞模擬器同時也提供海量熱門的漢化版游戲免…

matlab脈沖信號并繪制波形2025.6.11

以下是一個使用MATLAB生成5V、10MHz脈沖信號并繪制波形的示例代碼: % 5V 10MHz脈沖信號仿真 clc; clear; close all; % 參數設置 voltage = 5; % 信號幅度(V) frequency = 10e6; % 脈沖頻率(10MHz) duty_cycle =

ElasticJob初探

依賴版本 JDK版本是&#xff1a;jdk17 springboot版本 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.2.4</version></parent>zookeeper elasticjo…

【Vue3】(三)vue3中的pinia狀態管理、組件通信方式及總結、插槽

目錄 一、vue3的pinia 1、什么是pinia&#xff1f; 2、為什么Vue3選擇pinia&#xff1f; 3、使用pinia的好處 4、安裝pinia 2、項目配置 3、存儲/讀取pinia中的數據 4、修改pinia中的數據 5、storeToRefs&#xff08;保持store中數據的響應式&#xff09; 6、getters 7、…