Linux使用mmap調(diào)用創(chuàng)建、讀寫和釋放共享內(nèi)存區(qū)域
1. 使用mmap創(chuàng)建映射區(qū)
mmap(memory map)是Linux系統(tǒng)提供的一個(gè)系統(tǒng)調(diào)用,用于將文件或設(shè)備映射到進(jìn)程的地址空間。它也可以用于創(chuàng)建匿名映射區(qū)域,實(shí)現(xiàn)進(jìn)程間的共享內(nèi)存。
mmap函數(shù)原型
#include <sys/mman.h> void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
參數(shù)說明:
addr:指定映射區(qū)的起始地址,通常設(shè)為NULL,讓系統(tǒng)自動(dòng)選擇合適的地址length:映射區(qū)域的大小prot:映射區(qū)域的保護(hù)標(biāo)志,如PROT_READ(可讀)、PROT_WRITE(可寫)、PROT_EXEC(可執(zhí)行)等flags:映射類型標(biāo)志,如MAP_SHARED(共享)、MAP_PRIVATE(私有)等fd:文件描述符,對于匿名映射設(shè)為-1offset:文件映射的偏移量,通常設(shè)為0
使用mmap創(chuàng)建共享內(nèi)存的步驟
- 打開或創(chuàng)建一個(gè)文件(對于文件映射)或使用匿名映射
- 調(diào)用mmap函數(shù)創(chuàng)建映射區(qū)
- 檢查mmap的返回值,確保映射成功
示例代碼:使用mmap創(chuàng)建匿名共享內(nèi)存
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main() {
// 定義映射區(qū)域大小
size_t size = 4096;
// 使用mmap創(chuàng)建匿名共享內(nèi)存
void *mapped = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
// 檢查映射是否成功
if (mapped == MAP_FAILED) {
perror("mmap failed");
return 1;
}
printf("Memory mapped at address %p\n", mapped);
// 使用共享內(nèi)存...
// 釋放映射區(qū)
if (munmap(mapped, size) == -1) {
perror("munmap failed");
return 1;
}
return 0;
}
2. 讀寫映射區(qū)
一旦成功創(chuàng)建了映射區(qū),進(jìn)程就可以像操作普通內(nèi)存一樣讀寫該區(qū)域。需要注意的是,如果映射的是文件,對映射區(qū)的修改會(huì)反映到實(shí)際文件中(當(dāng)使用MAP_SHARED標(biāo)志時(shí))。
讀寫映射區(qū)的注意事項(xiàng)
- 對于文件映射,修改的內(nèi)容會(huì)在適當(dāng)?shù)臅r(shí)機(jī)寫回文件(取決于系統(tǒng)實(shí)現(xiàn))
- 多個(gè)進(jìn)程同時(shí)訪問共享內(nèi)存時(shí)需要同步機(jī)制,如信號量、互斥鎖等
- 不要越界訪問映射區(qū)域,可能導(dǎo)致段錯(cuò)誤
示例代碼:讀寫映射區(qū)
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main() {
// 定義映射區(qū)域大小
size_t size = 4096;
// 使用mmap創(chuàng)建匿名共享內(nèi)存
void *mapped = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
// 檢查映射是否成功
if (mapped == MAP_FAILED) {
perror("mmap failed");
return 1;
}
// 寫入數(shù)據(jù)到映射區(qū)
char *message = "Hello, shared memory!";
strncpy((char *)mapped, message, strlen(message));
// 讀取并打印映射區(qū)內(nèi)容
printf("Read from shared memory: %s\n", (char *)mapped);
// 釋放映射區(qū)
if (munmap(mapped, size) == -1) {
perror("munmap failed");
return 1;
}
return 0;
}
3. 使用munmap釋放映射區(qū)
當(dāng)進(jìn)程不再需要使用映射區(qū)時(shí),應(yīng)該調(diào)用munmap函數(shù)釋放該區(qū)域,釋放的內(nèi)存可以被系統(tǒng)重新分配。
munmap函數(shù)原型
#include <sys/mman.h> int munmap(void *addr, size_t length);
參數(shù)說明:
addr:要釋放的映射區(qū)的起始地址,必須是mmap返回的地址length:要釋放的區(qū)域大小,必須與mmap調(diào)用時(shí)的length參數(shù)相同
使用munmap的注意事項(xiàng)
- 確保傳入正確的地址和大小
- 不要重復(fù)釋放同一個(gè)映射區(qū)
- 釋放映射區(qū)后,不應(yīng)該再訪問該區(qū)域的內(nèi)存
示例代碼:使用munmap釋放映射區(qū)
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main() {
// 定義映射區(qū)域大小
size_t size = 4096;
// 使用mmap創(chuàng)建匿名共享內(nèi)存
void *mapped = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
// 檢查映射是否成功
if (mapped == MAP_FAILED) {
perror("mmap failed");
return 1;
}
// 使用共享內(nèi)存...
// 釋放映射區(qū)
if (munmap(mapped, size) == -1) {
perror("munmap failed");
return 1;
}
printf("Memory unmapped successfully\n");
return 0;
}
4. mmap的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
- 高效:共享內(nèi)存是最快的IPC機(jī)制,因?yàn)閿?shù)據(jù)不需要在內(nèi)核和用戶空間之間復(fù)制
- 靈活:可以映射文件或創(chuàng)建匿名共享內(nèi)存
- 可以與文件系統(tǒng)結(jié)合使用,實(shí)現(xiàn)數(shù)據(jù)持久化
缺點(diǎn)
- 需要額外的同步機(jī)制:多個(gè)進(jìn)程同時(shí)訪問共享內(nèi)存時(shí)需要同步
- 管理復(fù)雜:需要手動(dòng)管理映射區(qū)的創(chuàng)建和釋放
- 安全性較低:共享內(nèi)存對所有具有訪問權(quán)限的進(jìn)程可見
5. 實(shí)際應(yīng)用場景
- 大數(shù)據(jù)處理:多個(gè)進(jìn)程共享處理大數(shù)據(jù)集
- 實(shí)時(shí)系統(tǒng):需要低延遲數(shù)據(jù)交換的系統(tǒng)
- 數(shù)據(jù)庫系統(tǒng):多個(gè)進(jìn)程共享數(shù)據(jù)緩存
- 圖形處理:多個(gè)進(jìn)程共享圖像數(shù)據(jù)
6. 總結(jié)
mmap是Linux中實(shí)現(xiàn)共享內(nèi)存的重要工具,它提供了一種高效的方式讓多個(gè)進(jìn)程共享內(nèi)存區(qū)域。通過合理使用mmap、munmap以及適當(dāng)?shù)耐綑C(jī)制,可以實(shí)現(xiàn)高效的進(jìn)程間通信。在實(shí)際應(yīng)用中,需要根據(jù)具體需求選擇合適的IPC機(jī)制,并在性能、安全性和復(fù)雜性之間做出權(quán)衡。
以上就是Linux使用mmap調(diào)用創(chuàng)建、讀寫和釋放共享內(nèi)存區(qū)域的詳細(xì)內(nèi)容,更多關(guān)于Linux mmap操作共享內(nèi)存區(qū)域的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
學(xué)習(xí)在kernel態(tài)下使用NEON對算法進(jìn)行加速的方法
這篇文章主要介紹了學(xué)習(xí)在kernel態(tài)下使用NEON對算法進(jìn)行加速的方法,一起來學(xué)習(xí)下,大大提高數(shù)據(jù)運(yùn)算的效率。2017-11-11
Linux date 時(shí)間設(shè)置同步命令分享
Linux服務(wù)器運(yùn)行久時(shí),系統(tǒng)時(shí)間就會(huì)存在一定的誤差,一般情況下可以使用date命令進(jìn)行時(shí)間設(shè)置,但在做數(shù)據(jù)庫集群分片等復(fù)雜操作時(shí)對多臺(tái)機(jī)器的時(shí)間差是有要求的,此時(shí)就需要使用ntpdate進(jìn)行時(shí)間同步。2018-04-04
使用fcntl系統(tǒng)函數(shù)在Linux下改變文件屬性的操作指南
在 Linux 系統(tǒng)編程中,fcntl 是一個(gè)非常強(qiáng)大且靈活的系統(tǒng)調(diào)用,允許開發(fā)者對文件描述符進(jìn)行各種操作,包括設(shè)置和獲取文件屬性、管理文件鎖等,本文將深入探討 fcntl 的功能及其在實(shí)際開發(fā)中的應(yīng)用,需要的朋友可以參考下2025-10-10
CentOS 7 安裝 MySQL 5.6遇到的各種問題小結(jié)
在一測試服務(wù)器(CentOS Linux release 7.2.1511)上安裝MySQL 5.6(5.6.19 MySQL Community Server)時(shí)遇到了很多奇葩問題,今天小編給大家總結(jié)了關(guān)于entOS 7 安裝 MySQL 5.6遇到的各種問題,需要的朋友一起看看吧2016-11-11
Linux服務(wù)器如何修改默認(rèn)的遠(yuǎn)程連接端口
這篇文章主要介紹了Linux服務(wù)器如何修改默認(rèn)的遠(yuǎn)程連接端口問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12
Linux進(jìn)程使用文件進(jìn)行通信的常用方法
在Linux系統(tǒng)中,進(jìn)程間通信(IPC)是構(gòu)建復(fù)雜應(yīng)用的關(guān)鍵技術(shù),使用文件進(jìn)行通信是一種簡單而有效的方法,特別適合需要持久化數(shù)據(jù)或跨系統(tǒng)邊界的場景,本文將介紹幾種主要的文件通信技術(shù)及其應(yīng)用場景,需要的朋友可以參考下2025-11-11
Linux服務(wù)器快速搭建MinIO對象存儲(chǔ)全過程
在Linux服務(wù)器上搭建MinIO存儲(chǔ)服務(wù)器的步驟,MinIO支持從二進(jìn)制文件或包管理器下載,用戶需要配置環(huán)境變量、創(chuàng)建存儲(chǔ)目錄并設(shè)置服務(wù)權(quán)限,然后啟動(dòng)服務(wù)并訪問Web控制臺(tái)進(jìn)行驗(yàn)證,文章還提到可配置防火墻、Nginx反向代理及多節(jié)點(diǎn)部署2025-09-09

