簡介: CSDN博客專家,專注Android/Linux系統,分享多mic語音方案、音視頻、編解碼等技術,與大家一起成長!
優質專欄:Audio工程師進階系列【原創干貨持續更新中……】🚀
優質專欄:多媒體系統工程師系列【原創干貨持續更新中……】🚀
優質視頻課程:AAOS車載系統+AOSP14系統攻城獅入門實戰課【原創干貨持續更新中……】🚀
人生格言: 人生從來沒有捷徑,只有行動才是治療恐懼和懶惰的唯一良藥.
🍉🍉🍉文章目錄🍉🍉🍉
- 🌻1.前言
- 🌻2.Linux mmap介紹
- 🌻3.代碼實例
- 🐓3.1 基本內存映射和讀取
- 🐓3.2 共享內存映射和寫入
- 🐓3.3 匿名內存映射
🌻1.前言
本篇目的:Linux之共享內存mmap用法實例
🌻2.Linux mmap介紹
- Linux下的
mmap
是一種內存映射的機制,允許用戶空間的應用程序將文件或設備直接映射到內存中。這種機制可以提供高效的大文件讀寫方式,同時避免了傳統文件讀寫操作的系統調用開銷。 mmap
機制將文件內容映射到進程的地址空間,使得進程可以通過操作內存的方式讀寫文件,而無需進行文件系統的I/O操作。這對于頻繁訪問大型文件的應用程序來說,可以顯著提高性能,因為它減少了數據在用戶空間和內核空間之間的拷貝次數。mmap
函數的原型定義在<sys/mman.h>
頭文件中,其基本調用形式如下:
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
- 參數說明如下:
addr
:指定映射內存的起始地址,通常設置為NULL
,讓系統自動選擇。length
:要映射的內存長度。prot
:映射區域的保護模式,可以是PROT_READ
、PROT_WRITE
、PROT_EXEC
等,或者它們的組合。flags
:映射區域的標志,常用的標志有MAP_SHARED
、MAP_PRIVATE
、MAP_ANONYMOUS
、MAP_GROWSDOWN
等。fd
:文件描述符,來自于之前對文件的open
操作。offset
:文件映射開始的偏移量,通常是對文件大小的偏移。
mmap
的返回值是一個void*
類型的指針,指向映射內存的起始地址。如果映射失敗,則返回NULL
,并設置errno
來指示錯誤。
內存映射通常分為兩種模式:
MAP_SHARED
:映射區域的內存可以被多個進程共享。對共享映射區域的修改會立即反映到文件系統中,反之亦然。MAP_PRIVATE
:映射區域的內存對其他進程是不可見的。對私有映射區域的修改不會影響文件系統,但可以提高數據訪問的效率。
此外,mmap
還可以用于匿名內存映射,即不與任何文件關聯的內存映射。這時可以使用MAP_ANONYMOUS
標志,并通常與/dev/zero
設備文件一起使用,以分配不來自文件的內存。
- 內存映射的解除可以通過
munmap
函數實現,其原型如下:
int munmap(void *addr, size_t length);
- 參數
addr
是mmap
返回的地址,length
是要解除映射的長度。成功時返回0
,失敗時返回-1
并設置errno
。 mmap
機制在Linux系統中廣泛應用于高效的數據處理,如數據庫、緩存、文件共享等。它也是許多高性能服務器和客戶端應用程序的關鍵特性之一。- 使用
mmap
時,開發者需要充分理解內存保護機制,以避免可能的競態條件和數據不一致問題。
🌻3.代碼實例
🐓3.1 基本內存映射和讀取
#include <iostream>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <string>int main() {// 打開文件int fd = open("example.txt", O_RDONLY);if (fd == -1) {std::cerr << "Open file failed." << std::endl;return 1;}// 映射文件void* map = mmap(NULL, 1024, PROT_READ, MAP_PRIVATE, fd, 0);if (map == MAP_FAILED) {std::cerr << "Map memory failed." << std::endl;close(fd);return 1;}// 讀取映射的內容char buffer[1024];std::memcpy(buffer, map, 1024);// 輸出內容std::cout << "Content of the file: " << buffer << std::endl;// 解除映射munmap(map, 1024);// 關閉文件close(fd);return 0;
}
🐓3.2 共享內存映射和寫入
#include <iostream>
#include <sys/mman.h>
#include <unistd.h>
#include <string>int main() {// 創建共享內存文件int fd = open("shared_memory.txt", O_RDWR | O_CREAT, 0644);if (fd == -1) {std::cerr << "Open file failed." << std::endl;return 1;}// 映射文件void* map = mmap(NULL, 1024, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);if (map == MAP_FAILED) {std::cerr << "Map memory failed." << std::endl;close(fd);return 1;}// 寫入內容std::string message("Hello, shared memory!");std::memcpy(map, message.c_str(), message.size());// 輸出內容char buffer[1024];std::memcpy(buffer, map, 1024);std::cout << "Written content: " << buffer << std::endl;// 解除映射munmap(map, 1024);// 關閉文件close(fd);return 0;
}
🐓3.3 匿名內存映射
#include <iostream>
#include <sys/mman.h>
#include <unistd.h>
#include <string>int main() {// 創建一個匿名內存區域void* map = mmap(NULL, 1024, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);if (map == MAP_FAILED) {std::cerr << "Map memory failed." << std::endl;return 1;}// 寫入內容std::string message("Hello, anonymous memory!");std::memcpy(map, message.c_str(), message.size());// 輸出內容char buffer[1024];std::memcpy(buffer, map, 1024);std::cout << "Written content: " << buffer << std::endl;// 輸出內容char buffer[1024];std::memcpy(buffer, map, 1024);std::cout << "Written content: " << buffer << std::endl;// 解除映射munmap(map, 1024);return 0;
}