mmap核心原理和用途及其與內存映射段的關系

mmap 是 Linux/Unix 系統中的一個關鍵系統調用,全稱是 Memory Map(內存映射)。它的核心功能是將 文件、設備或匿名內存 直接映射到進程的虛擬地址空間,從而實現高效的內存訪問和操作。以下是其核心原理和用途的詳細說明:


1. 核心功能

  • 內存映射文件:將文件內容映射到進程的虛擬內存中,直接通過指針讀寫文件,無需傳統的 read/write 系統調用。
  • 匿名內存映射:分配不關聯任何文件的純內存塊(類似 malloc,但更靈活)。
  • 共享內存:多個進程可映射同一塊內存,實現高效進程間通信(IPC)。

2. 工作原理

  • 系統調用原型

    void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
    
  • 參數說明

    • addr:建議的映射起始地址(通常設為 NULL,由內核自動選擇)。
    • length:映射區域的長度(需按頁對齊,如 4KB)。
    • prot:內存保護權限(如 PROT_READ | PROT_WRITE)。
    • flags:映射類型(MAP_SHARED 共享內存,MAP_PRIVATE 私有副本,MAP_ANONYMOUS 匿名內存等)。
    • fd:文件描述符(匿名映射時設為 -1)。
    • offset:文件映射的起始偏移量(通常為 0)。
  • 返回值:成功返回映射區域的起始地址,失敗返回 MAP_FAILED


3. 主要用途

(1) 高效文件 I/O

  • 直接讀寫內存:映射文件后,操作內存即操作文件,避免頻繁的 read/write 系統調用。
  • 惰性加載:文件內容按需加載到內存(缺頁中斷機制),適合處理大文件。
  • 示例
    int fd = open("data.txt", O_RDWR);
    char *ptr = mmap(NULL, file_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    ptr[0] = 'A'; // 直接修改文件內容
    munmap(ptr, file_size); // 解除映射
    

(2) 動態內存分配

  • 替代 mallocmalloc 在分配大塊內存時可能使用 mmap(通過 MAP_ANONYMOUS 標志)。
  • 匿名內存映射
    void *mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    

(3) 進程間共享內存(IPC)

  • 共享內存通信:多個進程映射同一文件或匿名內存,共享數據。
  • 示例
    // 進程 A
    void *shm = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    sprintf(shm, "Hello from Process A");// 進程 B(映射同一文件)
    printf("%s\n", (char*)shm); // 輸出 "Hello from Process A"
    

(4) 實現零拷貝(Zero-Copy)

  • 避免數據復制:網絡傳輸或文件操作時,直接映射內存到用戶空間,減少內核與用戶空間的數據拷貝。

4. 與 malloc/brk 的對比

特性mmapmalloc/brk
內存來源文件、匿名內存、共享內存堆內存(通過 brksbrk
分配粒度按頁(如 4KB)按字節(實際可能按塊管理)
碎片問題較少(大塊獨立映射)較多(頻繁分配釋放導致碎片)
適用場景大內存分配、文件映射、IPC常規小內存分配
性能開銷初始映射開銷大,后續訪問快分配速度快,但碎片可能影響性能

5. 優缺點

  • 優點
    • 高效文件操作:減少系統調用和數據拷貝。
    • 共享內存:跨進程通信速度快。
    • 靈活內存管理:支持動態調整映射區域(mremap)。
  • 缺點
    • 內存對齊要求:映射長度需按頁對齊。
    • 資源泄漏風險:需手動調用 munmap 釋放。
    • 文件同步問題:修改后需調用 msync 確保數據寫入磁盤。

6. 關鍵注意事項

  • 錯誤處理:檢查返回值是否為 MAP_FAILED,并用 perror 診斷錯誤。
  • 釋放內存:使用 munmap 釋放映射區域,不可用 free
  • 同步數據:修改文件映射后,調用 msync 確保數據持久化。
  • 線程安全:多線程中操作同一映射區域需加鎖。

7. 示例代碼(匿名內存分配)

#include <sys/mman.h>int main() {size_t size = 4096; // 1 頁大小// 分配匿名內存(可讀可寫)void *mem = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);if (mem == MAP_FAILED) {perror("mmap failed");return 1;}// 使用內存memset(mem, 0, size);// 釋放munmap(mem, size);return 0;
}

8.mmap與內存映射段

mmap內存映射段(Memory-Mapped Segment)是操作系統內存管理中的兩個緊密相關的概念。mmap 是用戶態操作內存映射段的接口,而內存映射段是進程虛擬地址空間中用于存儲映射內容(如文件、共享內存等)的區域。以下是二者的關系及詳細說明:

(1) 內存映射段是什么?

在進程的虛擬地址空間中,內存映射段(也稱為 內存映射區域)是專門用于存放通過 mmap 系統調用映射的內容的區域。其典型位置如下(以 Linux 進程地址空間為例):

高地址
┌───────────────────────┐
│ 棧(Stack) │
├───────────────────────┤
│ … │
├───────────────────────┤
│ 堆(Heap) │ ← 通過 brk/sbrkmalloc 分配
├───────────────────────┤
│ 內存映射段(Memory-Mapped Region)│ ← 通過 mmap 映射的內容
├───────────────────────┤
│ 未初始化數據段(BSS) │
├───────────────────────┤
│ 已初始化數據段(Data) │
├───────────────────────┤
│ 代碼段(Text) │
└───────────────────────┘
低地址

內存映射段的特點:

  • 動態擴展:大小由 mmap 的映射操作決定,可動態增長或收縮。
  • 多種用途:可包含文件映射、共享內存、匿名內存等。
  • 分頁管理:按頁(如 4KB)對齊,由內核通過缺頁中斷(Page Fault)按需加載數據。

(2) mmap 如何操作內存映射段?

mmap 是用戶程序與內存映射段交互的核心接口,具體行為如下:

① 映射文件到內存映射段
  • 通過 mmap 將文件內容映射到內存映射段,進程通過指針直接讀寫文件,無需 read/write
  • 示例
    int fd = open("data.txt", O_RDWR);
    char *ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    // ptr 指向內存映射段中的文件內容
    ptr[0] = 'X'; // 直接修改文件
    munmap(ptr, 4096); // 解除映射
    
② 分配匿名內存
  • 使用 MAP_ANONYMOUS 標志創建不關聯文件的純內存塊,常用于替代 malloc 分配大內存。
  • 示例
    void *mem = mmap(NULL, 1024*1024, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    // mem 指向內存映射段中的匿名內存
    
③ 共享內存(IPC)
  • 多個進程通過 mmap 映射同一文件或匿名內存,實現高效數據共享。
  • 示例
    // 進程 A
    void *shm = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    sprintf(shm, "Hello");// 進程 B(映射同一文件)
    printf("%s\n", (char*)shm); // 輸出 "Hello"
    

(3) 內存映射段的管理機制

① 分頁與缺頁中斷
  • 內存映射段的內容按頁(如 4KB)管理。
  • 初次訪問映射區域時觸發 缺頁中斷,內核將文件內容或物理內存加載到頁表中。
② 寫時復制(Copy-on-Write)
  • 若使用 MAP_PRIVATE 標志,修改內存映射段時會觸發寫時復制,生成進程私有的副本。
③ 同步與持久化
  • 修改文件映射后,需調用 msync 強制將內存中的數據寫回磁盤。
  • 匿名映射的內容隨進程結束自動釋放。

(4) mmap 與內存映射段的關系總結

特性mmap 系統調用內存映射段
角色操作接口(用戶態函數)存儲區域(進程地址空間的一部分)
功能創建、刪除、調整內存映射存放文件、共享內存、匿名內存等內容
生命周期顯式調用 mmapmunmap 控制由內核管理,隨進程終止或 munmap 釋放
性能優化減少數據拷貝、支持零拷貝按需加載(惰性分配)、分頁管理

(5) 常見問題

mmap 分配的匿名內存與堆內存(malloc)有何區別?
  • 匿名內存:位于內存映射段,按頁分配,適合大塊內存,釋放直接通過 munmap
  • 堆內存:通過 brk/sbrkmalloc 分配,位于堆段,適合小塊內存,可能產生碎片。
② 內存映射段會占用物理內存嗎?
  • 不會立即占用。內核通過缺頁中斷按需分配物理內存(惰性加載)。
③ 內存映射段的大小限制?
  • 受進程虛擬地址空間限制(如 32 位系統最大 4GB,64 位系統理論極大)。

(6) 總結

  • mmap 是操作內存映射段的工具,內存映射段是 mmap 映射內容的存儲區域。
  • 文件映射、共享內存、匿名內存分配等均通過 mmap 在內存映射段中實現。
  • 理解二者的關系,有助于優化文件 I/O、內存分配和進程間通信的設計。

通過 mmap,開發者可以直接操控內存與文件、設備或共享內存的關系,這在處理高性能 I/O、內存數據庫、跨進程通信等場景中非常有用。理解其原理和適用場景,能顯著優化程序的效率和資源管理能力。

創作不易,希望大家多多支持,有什么想法歡迎討論🌹🌹

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

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

相關文章

數據庫概論速成期中版

文章目錄 引論數據庫用戶Casual usersNaive usersApplication programmersDatabase administrators 關系模型CAP數據庫兩種描述關系數據庫的方式簡單總結 第一范式規則第二范式規則舉個例子符合第二規則的操作不符合第二規則的操作 第三范式規則key,superkey,null values,主鍵&…

解決調用Claude 3.7接口 403 Request not allowed問題

1. 遇到問題 Python 基于 Langchain 對接 Claude 3.7 大模型接口進行問答時&#xff0c;由于國內不在Claude支持的國家和地區&#xff0c;所以一直調不通&#xff0c;錯誤 anthropic.PermissionDeniedError: Error code: 403 - {error: {type: forbidden, message: Request…

Vue2+Vue3學習筆記

Vue基礎介紹 下載并安裝vue.js v2 https://v2.cn.vuejs.org/https://v2.cn.vuejs.org/ v3 https://v3.cn.vuejs.org/ 會重定向到Vue.js - 漸進式 JavaScript 框架 | Vue.jsVue.js - 漸進式的 JavaScript 框架https://cn.vuejs.org/ 從v2過渡到v3 在F盤創建v2v3學習筆記 并…

2025年KBS新算法 SCI1區TOP:長穎燕麥優化算法AOO,深度解析+性能實測

目錄 1.摘要2.算法原理3.結果展示4.參考文獻5.文章&代碼獲取 1.摘要 本文提出了一種新穎的元啟發式算法——長穎燕麥優化算法&#xff08;AOO&#xff09;&#xff0c;該算法靈感來自動畫燕麥在環境中的自然行為。AOO模擬了長穎燕麥的三種獨特行為&#xff1a;(i) 通過自然…

CentosLinux系統crontab發現執行刪除命令失效解決方法

權限或安全策略限制 ??可能場景??&#xff1a; ??### ??目錄權限沖突??&#xff1a; 你的目錄權限為 drwxr-xr-x&#xff08;屬主 mssql&#xff09;&#xff0c;但 cron 任務以 root 執行。 ??風險點??&#xff1a;若目錄內文件屬主為 mssql 且權限為 700&…

后驗概率最大化(MAP)估計算法原理以及相具體的應用實例附C++代碼示例

1. MAP估計基本原理 MAP&#xff08;Maximum A Posteriori&#xff0c;最大后驗概率估計&#xff09;是貝葉斯推斷中的重要概念&#xff0c;它的目標是&#xff1a; 給定觀測數據&#xff0c;找到使得后驗概率最大的參數值。 公式化表示&#xff1a; [ θ MAP arg ? max ?…

16、路由守衛:設置魔法結界——React 19 React Router

一、魔法結界的本質 "路由守衛是霍格沃茨城堡的隱身斗篷&#xff0c;在時空裂隙中精準控制維度躍遷&#xff01;" 魔法部交通司官員揮舞魔杖&#xff0c;React Router 的嵌套路由在空中交織成星軌矩陣。 ——基于《國際魔法聯合會》第7號時空協議&#xff0c;路由守…

從車道檢測項目入門open cv

從車道檢測項目入門open cv 前提聲明&#xff1a;非常感謝b站up主 嘉然今天吃帶變&#xff0c;感謝其視頻的幫助。同時希望各位大佬積積極提出寶貴的意見。&#x1f60a;&#x1f60a;&#x1f60a;(???)(●’?’●)╰(▽)╯ github地址&#xff1a;https://github.com/liz…

【行業特化篇3】制造業簡歷優化指南:技術參數與標準化流程的關鍵詞植入藝術

寫在最前 作為一個中古程序猿,我有很多自己想做的事情,比如埋頭苦干手搓一個低代碼數據庫設計平臺(目前只針對寫java的朋友),比如很喜歡幫身邊的朋友看看簡歷,講講面試技巧,畢竟工作這么多年,也做到過高管,有很多面人經歷,意見還算有用,大家基本都能拿到想要的offe…

如何在本地部署小智服務器:從源碼到全模塊運行的詳細步驟

小智聊天機器人本地后臺服務器源碼全模塊部署 作者&#xff1a;林甲酸 -不是小女子也不是女漢子 是大女子 更新日期&#xff1a;2025年4月29日 &#x1f3af; 前言&#xff1a;為什么要寫這篇教程&#xff1f; 上周按照蝦哥小智服務器的教程去部署本地后臺&#xff0c;我用的是…

github開源項目添加開源協議,使用很簡單

直接在 GitHub 網頁上創建 進入你的 GitHub 倉庫 打開你的項目倉庫頁面&#xff08;如 https://github.com/用戶名/倉庫名&#xff09;。 點擊 "Add file" → "Create new file" 在倉庫主頁&#xff0c;點擊右上角的 "Add file" 按鈕&#xff…

8.idea創建maven項目(使用Log4j日志記錄框架+Log4j 介紹)

8.idea創建maven項目(使用Log4j日志記錄框架Log4j 介紹) 在 IntelliJ IDEA 的 Maven 項目中引入了 Log4j&#xff0c;并配置了日志同時輸出到控制臺和文件。 Log4j 提供了靈活的日志配置選項&#xff0c;可以根據項目需求調整日志級別、輸出目標和格式。 1. 創建 Maven 項目 …

【和春筍一起學C++】函數——C++的編程模塊

目錄 1. 原型句法 2. 函數分類 3. 函數參數之按值傳遞 4. 數組作為函數參數 在C中&#xff0c;要使用函數&#xff0c;必須要有這三個方面&#xff1a; 函數原型&#xff0c;函數原型描述了函數到編譯器的接口&#xff0c;函數原型一般放在include文件中。函數原型告訴編譯…

深挖Java基礎之:認識Java(創立空間/先導:Java認識)

今天我要介紹的是在Java中對Java的一些基本語法的認識與他們的運用&#xff0c;以及擬舉例子說明和運用場景&#xff0c;優勢和劣勢&#xff0c; 注&#xff1a;本篇文章是對Java的一些基本的&#xff0c;簡單的代碼塊的一些內容&#xff0c;后續會講解在Java中的變量類型&…

Python+Selenium+Pytest+Allure PO模式UI自動化框架

一、框架結構 allure-report&#xff1a;測試報告base&#xff1a;定位元素封裝data&#xff1a;數據log&#xff1a;日志文件page&#xff1a;頁面封裝文件夾report&#xff1a;緩存報告testcases&#xff1a;測試用例層utils&#xff1a;工具類run.py&#xff1a;執行文件 二…

博物館除濕控濕保衛戰:M-5J1R 電解除濕科技如何重塑文物守護的未來

在盧浮宮幽深的長廊里&#xff0c;達芬奇的《蒙娜麗莎》正經歷著一場看不見的戰爭——不是來自時間的侵蝕&#xff0c;而是空氣中無形的水分子。每一件文物都在與濕度進行著無聲的抗爭&#xff0c;這場抗爭關乎人類文明的延續。濕度&#xff0c;這個看不見的文物殺手&#xff0…

【嘉立創EDA】如何找到曲線和直線的交點,或找到弧線和直線的交點

文章路標?? :one: 文章解決問題:two: 主題內容:three: 參考方法be end..1?? 文章解決問題 操作環境:嘉立創EDA專業版 V2.2.38 本文使用嘉立創EDA,描述如何快速找到曲線和直線交點的方法,這里的曲線包括了弧線等。本文將此過程記錄,以供有需要的讀者參考。 2?? 主題…

大語言模型能否替代心理治療師的深度拓展研究:fou

大語言模型能否替代心理治療師的深度拓展研究 在科技初創企業和研究領域,大型語言模型(LLMs)用于替代心理健康服務提供者的應用備受關注。但研究人員通過對主要醫療機構治療指南的梳理回顧,并對當前 LLMs(如 gpt-4o)進行實驗評估后發現,LLMs 存在對心理疾病患者表達污名…

【linux】Chrony服務器

簡介 1.1 時間的重要性 由于 IT 系統中&#xff0c;準確的計時非常重要&#xff0c;有很多種原因需要準確計時&#xff1a; 在網絡傳輸中&#xff0c;數據包括和日志需要準確的時間戳 各種應用程序中&#xff0c;如訂單信息&#xff0c;交易信息等 都需要準確的時間戳 1.2 時區…

mysql查看哪些表的自增id已超過某個值

場景 想看哪些表數據比較大&#xff0c;如果用count 比較慢&#xff0c;同時表設計如果是自增&#xff0c;有沒有辦法一次查出自增id已超過某值的所有表呢。 方法 SELECT AUTO_INCREMENT,TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA 庫名 AND AUTO_INCRE…