Linux 記憶體管理之 mmap 解析(二)

2021-07-03 20:25:23 字數 3587 閱讀 2269

1、mmap()系統呼叫形式

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

mmap的作用是對映檔案描述符fd指定檔案的 [off,off + len]區域至呼叫程序的[addr, addr + len]的記憶體區域, 如下圖所示:

引數fd:為即將對映到程序空間的檔案描述字,一般由open()返回,同時,fd可以指定為-1,此時須指定flags引數中的

map_anon,表明進行的是匿名對映(不涉及具體的檔名,避免了檔案的建立及開啟,很顯然只能用於具有親緣關係的

程序間通訊)。

引數prot :指定共享記憶體的訪問許可權。可取如下幾個值的或:prot_read(可讀) , prot_write (可寫), prot_exec (可執行), prot_none(不可訪問)。

引數flags:由以下幾個常值指定:map_shared , map_private , map_fixed,其中,map_shared , map_private必

選其一,而map_fixed則不推薦使用。

引數offset:一般設為0,表示從檔案頭開始對映。

引數addr:指定檔案應被對映到程序空間的起始位址,一般被指定乙個空指標,此時選擇起始位址的任務留給核心來完成。函

數的返回值為最後檔案對映到程序空間的位址,程序可直接操作起始位址為該值的有效位址。

2、參考**

範例中使用的測試檔案 data.txt:

aaaaaaaaa  

bbbbbbbbb

ccccccccc

ddddddddd

(1)通過共享對映的方式修改檔案

#include 

#include

#include

#include

#include

#include

#include

#define buf_size 100

int main(int argc, char **argv)

/* 開啟檔案 */

if ((fd = open(argv[1], o_rdwr)) < 0)

/* 獲取檔案的屬性 */

if ((fstat(fd, &sb)) == -1)

/* 將檔案對映至程序的位址空間 */

prot_write, map_shared, fd, 0)) == (void *)-1)

/* 對映完後, 關閉檔案也可以操縱記憶體 */

close(fd);

/* 修改乙個字元,同步到磁碟檔案 */

perror("msync");

}/* 釋放儲存對映區 */

perror("munmap");

}return

0;}

(2) 使用共享對映實現兩個程序之間的通訊

兩個程式對映同乙個檔案到自己的位址空間, 程序a先執行, 每隔兩秒讀取對映區域, 看是否發生變化.

程序b後執行, 它修改對映區域, 然後推出, 此時程序a能夠觀察到儲存對映區的變化

程序a的**:

#include 

#include

#include

#include

#include

#include

#include

#define buf_size 100

int main(int argc, char **argv)

/* 開啟檔案 */

if ((fd = open(argv[1], o_rdwr)) < 0)

/* 獲取檔案的屬性 */

if ((fstat(fd, &sb)) == -1)

/* 將檔案對映至程序的位址空間 */

prot_write, map_shared, fd, 0)) == (void *)-1)

/* 檔案已在記憶體, 關閉檔案也可以操縱記憶體 */

close(fd);

/* 每隔兩秒檢視儲存對映區是否被修改 */

while (1)

return

0;}

程序b**

#include 

#include

#include

#include

#include

#include

#include

#define buf_size 100

int main(int argc, char **argv)

/* 開啟檔案 */

if ((fd = open(argv[1], o_rdwr)) < 0)

/* 獲取檔案的屬性 */

if ((fstat(fd, &sb)) == -1)

/* 私有檔案對映將無法修改檔案 */

prot_write, map_private, fd, 0)) == (void *)-1)

/* 對映完後, 關閉檔案也可以操縱記憶體 */

close(fd);

/* 修改乙個字元 */

return

0;}

(3)通過匿名對映實現父子程序通訊

#include 

#include

#include

#include

#define buf_size 100

int main(int argc, char** argv)

sprintf(p_map, "%s", "hi, this is father");

sleep(2);

printf("parent got a message: %s\n", p_map);

return

0;}

(4)對mmap()返回位址的訪問

linux採用的是頁式管理機制。對於用mmap()對映普通檔案來說,程序會在自己的位址空間新增一塊空間,空間大小由 mmap() 的 len 引數指定,注意,程序並不一定能夠對全部新增空間都能進行有效訪問。程序能夠訪問的有效位址大小取決於檔案被對映部分的大小。簡單的說,能夠容納檔案被對映部分大小的最少頁面個數決定了程序從 mmap() 返回的位址開始,能夠有效訪問的位址空間大小。超過這個空間大小,核心會根據超過的嚴重程度返回傳送不同的訊號給程序。可用如下圖示說明:

Linux記憶體管理 mmap

mmap munmap是常用的乙個系統呼叫,使用場景是 分配記憶體 讀寫大檔案 連線動態庫檔案 多程序間共享記憶體。mmap munmap函式宣告如下 include void mmap void addr,size t length,int prot,int flags,int fd,off t ...

Linux記憶體管理 9 mmap

專題 linux記憶體管理專題 mmap munmap是常用的乙個系統呼叫,使用場景是 分配記憶體 讀寫大檔案 連線動態庫檔案 多程序間共享記憶體。更詳細解讀參考 linux記憶體管理 9 mmap 補充 mmap munmap函式宣告如下 include void mmap void addr,s...

Linux的記憶體對映之mmap

共享記憶體可以說是最有用的程序間通訊方式,也是最快的ipc形式,因為程序可以直接讀寫記憶體,而不需要任何資料的拷貝。對於像管道和訊息佇列等通訊方式,則需要在核心和使用者空間進行四次的資料拷貝,而共享記憶體則只拷貝兩次資料 一次從輸入檔案到共享記憶體區,另一次從共享記憶體區到輸出檔案。實際上,程序之間...