深入淺出mmap內存映射

一、mmap內存映射主要用在哪裡

mmap內存映射是一種將文件或其他對象映射到進程地址空間的機制,主要用於以下場景:

1. 文件映射:在許多操作系統中,可以通過mmap將一個文件的整個內容映射到進程的地址空間中。這種技術被廣泛應用於一些高效的文件操作,如數據庫系統,谷歌的大量的Web服務器和開發一些離線處理的大數據應用。

2. 共享內存:mmap還可以將一塊共享內存映射到多個進程的地址空間中,這些進程可以直接通過訪問共享內存來交換數據,可以在這些進程間實現高效的通信。

3. 匿名映射:通過mmap可以在進程的地址空間中分配一塊虛擬內存,來實現不同進程之間的數據共享,這種匿名映射的內存映射技術被廣泛應用於Unix/Linux系統中的共享庫,而且在現代操作系統中也是非常有用的。

二、mmap內存映射函數的參數

mmap函數在使用時需要傳遞四個必要的參數,它們依次是:

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

1. addr:可選的指定映射的開始地址,通常將它設置為0,讓系統自動選擇一個未使用的地址作為映射的地址,這是一個好的習慣。

2. length:映射的大小,單位是字節。

3. prot:映射區域的保護方式,可以是下面幾個選項中的一個或多個組合:

  • PROT_EXEC:表示可執行的代碼
  • PROT_READ:表示可讀
  • PROT_WRITE:表示可寫
  • PROT_NONE:表示不可訪問

4. flags:控制映射區域的各種屬性,可以通過以下的選項進行組合:

  • MAP_PRIVATE:建立一個寫入時拷貝(COW)的私有映射,不會改變原對象。
  • MAP_SHARED:對映射區域的寫入數據會複製迴文件

5. fd:需要映射的文件描述符。

6. offset:文件映射的偏移量,通常將它設置為0,表示從文件頭開始。

三、mmap內存映射原理

mmap內存映射是基於虛擬內存進行的,它允許應用程序像訪問內存一樣訪問磁盤上的文件,實際上是將文件的一段內容直接映射到進程地址空間的一段區域中,這導致了一系列的優點:

  • 有時不需要將整個文件都讀入內存即可開始工作
  • 當需要更新文件時,不需要顯式地拷貝到磁盤上
  • 不會造成page cache的污染,同時內存限制也大大增加

它的底層實現利用了虛擬內存的一個非常重要的好處,即虛擬內存能夠將物理內存和交換空間(磁盤)組合在一起使用。CPU需要訪問進程的某個虛擬地址時,會計算出這個地址在物理內存或者磁盤上的位置,如果在物理內存上,那麼直接訪問;否則就會將物理內存中不常用的頁替換到磁盤上,然後再從磁盤上讀入需要的頁。

四、mmap內存映射內核

mmap內存映射是由操作系統內核虛擬內存系統的具體實現來支持的。具體來說,內核在mmap函數調用時,會向虛擬內存子系統發送一個請求,讓它將一個虛擬內存區域映射到用戶進程的地址空間中。當進程訪問這個虛擬內存區域時,虛擬內存子系統會將對應的數據從文件中讀入,或者將數據寫回磁盤上。

這個虛擬內存區域是由用戶進程管理的,稱為內存映射區域。在虛擬內存系統中,被映射文件的每一個頁都有多個副本,既可以在文件中存在,也可以在內存中存在。因此,當進程對一個虛擬內存區域中的某個頁進行訪問時,虛擬內存系統會將這個頁映射到多個虛擬內存區域中,並將這些虛擬內存區域轉換為物理頁框,使得這些虛擬內存區域實際上都指向了同一個物理頁。

五、mmap內存映射大小限制

在64位系統中,由於地址空間的大小可以達到2^64個字節,因此可以創建非常大的內存映射區域。但是在32位系統中,由於地址空間的大小只有2^32個字節,因此內存映射的大小受到了一定的限制,在一些系統中可以定義一些參數來調整限制的大小。

六、mmap內存映射 文件為空

當被映射的文件為空時,根據函數的flags參數的不同,mmap內存映射的行為也有所不同。

1. 如果標誌選項包含MAP_PRIVATE,則映射區域中的內容將被初始化為0。

2. 如果標誌選項包含MAP_SHARED,則映射區域的是未定義的,並且對該區域的訪問會產生總線錯誤(bus error)。

七、mmap內存映射bus error

當mmap映射區域為空時,在對映射區域進行寫入等操作時,會產生總線錯誤(bus error)。這是因為在嘗試使用空的映射區域時,訪問的內存地址無效。這時可以使用mmap函數的MAP_ANONYMOUS參數來初始化該映射區,例如:

char *ptr = mmap(NULL, sizeof(char)*512, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);

這樣就可以正確初始化一個空的映射區域了。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/287209.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-23 13:07
下一篇 2024-12-23 13:07

相關推薦

  • Python創建分配內存的方法

    在python中,我們常常需要創建並分配內存來存儲數據。不同的類型和數據結構可能需要不同的方法來分配內存。本文將從多個方面介紹Python創建分配內存的方法,包括列表、元組、字典、…

    編程 2025-04-29
  • Python變量在內存中的存儲

    該文章將從多個方面對Python變量在內存中的存儲進行詳細闡述,包括變量的聲明和賦值、變量的引用和指向、內存地址的變化、內存管理機制等。 一、聲明和賦值 在Python中,變量聲明…

    編程 2025-04-29
  • Python計算內存佔用

    Python是一種高級的、解釋性的、面向對象的、動態的程序語言,因其易於學習、易於閱讀、可移植性好等優點,越來越受到開發者的青睞。當我們編寫Python代碼時,可能經常需要計算程序…

    編程 2025-04-28
  • 使用Go-Redis獲取Redis集群內存使用率

    本文旨在介紹如何使用Go-Redis獲取Redis集群的內存使用率。 一、Go-Redis簡介 Go-Redis是一個用於連接Redis服務器的Golang客戶端。它支持Redis…

    編程 2025-04-28
  • Python mmap共享使用指南

    Python的mmap模塊提供了一種將文件映射到內存中的方法,從而可以更快地進行文件和內存之間的讀寫操作。本文將以Python mmap共享為中心,從多個方面對其進行詳細的闡述和講…

    編程 2025-04-27
  • Python內置函數——查看對象內存

    本文將介紹Python內置函數中,在開發中查看對象內存的相關函數。 一、id()函數 id()函數是Python內置函數,用於返回對象的唯一標識符,也就是對象在內存中的地址。 nu…

    編程 2025-04-27
  • Python進程池共享內存用法介紹

    本文將從多個方面詳細闡述Python進程池共享內存的相關知識,包括如何使用進程池、進程池的實現原理、進程池中的共享內存管理等。本文內容將涵蓋: 一、進程池的使用 進程池是一種有效的…

    編程 2025-04-27
  • 深入淺出統計學

    統計學是一門關於收集、分析、解釋和呈現數據的學科。它在各行各業都有廣泛應用,包括社會科學、醫學、自然科學、商業、經濟學、政治學等等。深入淺出統計學是指想要學習統計學的人能夠理解統計…

    編程 2025-04-25
  • 深入解析Redis內存淘汰策略

    Redis是一個高性能鍵值數據庫,由於其快速、穩定和易於使用,它已經成為很多應用程序中不可或缺的一部分。在使用Redis時,我們需要考慮內存管理問題。Redis內存淘汰策略是如何工…

    編程 2025-04-25
  • 解決SQL Server內存佔用高問題的方法

    一、關閉不必要的服務 在SQL Server安裝時,默認開啟了許多服務,包括SQL Server Browser,SQL Server Agent等。關閉不必要的服務可以釋放內存資…

    編程 2025-04-25

發表回復

登錄後才能評論