Linux的記憶體對映之mmap

2021-09-24 13:33:12 字數 3575 閱讀 8217

共享記憶體可以說是最有用的程序間通訊方式,也是最快的ipc形式,因為程序可以直接讀寫記憶體,而不需要任何資料的拷貝。對於像管道和訊息佇列等通訊方式,則需要在核心和使用者空間進行四次的資料拷貝,而共享記憶體則只拷貝兩次資料: 一次從輸入檔案到共享記憶體區,另一次從共享記憶體區到輸出檔案。實際上,程序之間在共享記憶體時,並不總是讀寫少量資料後就解除對映,有新的通訊時,再重新建立共享記憶體區域。而是保持共享區域,直到通訊完畢為止,這樣,資料內容一直儲存在共享記憶體中,並沒有寫回檔案。共享記憶體中的內容往往是在解除對映時才寫回檔案的。因此,採用共享記憶體的通訊方式效率是非常高的。

1.函式介紹

1.1 mmap

在linux中記憶體對映需要用到mmap函式,其函式原型如下:

void * mmap (void *addr,size_t len,int prot,int flags,int fd,off_t offset);
其引數介紹如下:

prot:對映區保護方式,其可選擇項如下:

prot_none:無許可權;

prot_read:讀許可權;

prot_write:寫許可權;

prot_exec:執行許可權;

flags:描述了對映的型別,其可選擇項如下:

map_fixed:開啟這個選項,則 addr 引數指定的位址是作為必須而不是建議;

map_shared:多個程序對同乙個檔案的對映是共享的,乙個程序對對映的記憶體做了修改,另乙個程序也會看到這種變化;

map_anonymous:匿名對映,對映區不與任何檔案關聯;

map_private:多個程序對同乙個檔案的對映不是共享的,乙個程序對對映的記憶體做了修改,另乙個程序並不會看到這種變化,也不會真的寫到檔案中去;

map_noreserve:不要為這個對映保留交換空間,當交換空間被保留,對對映區修改的可能會得到保證;當交換空間不被保留,同時記憶體不足,對對映區的修改會引起段違例訊號;

map_locked:鎖定對映區的頁面,從而防止頁面被交換出記憶體;

map_growsdown :用於堆疊,告訴核心vm系統,對映區可以向下擴充套件;

fd:檔案描述符;

offset:從檔案頭開始的偏移量,必須是頁大小的整數倍(在32位體系統結構上通常是4k);

1.2 msync

linux系統中將程序在對映空間的對共享內容的改變並不直接寫回到磁碟檔案中需要用到msync函式,其函式原型如下:

int  msync(void *addr,size_t len,int flags)

返回值:成功返回0,失敗返回-1。

其引數介紹如下:

flags:設定標誌位,其可選擇項如下:

ms_async:不管對映區是否更新,直接沖洗返回;

ms_sync:如果對映區更新了,則沖洗返回,如果對映區沒有更新,則等待,知道更新完畢,就沖洗返回;

ms_invalidate:丟棄對映區中和原檔案相同的部分;

1.3 munmap

linux中mmap函式用來建立對映關係,munmap函式則是用來解除對映關係,其函式原型如下:

int munmap( void * addr, size_t len );

返回值:成功返回0,失敗返回-1。

其引數介紹如下:

2 記憶體對映的應用

2.1 共享對映訪問或寫改檔案

原始碼如下:

#include #include #include #include #include #include #include int main(int argc, char **ar**)  

/* 獲取檔案的屬性 */

struct stat sb;

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

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

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

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

close(fd);

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

perror("msync");

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

perror("munmap");

} return 0;

}

2.2 共享對映實現程序通訊

程序a原始碼:

#include #include #include #include #include #include #include int main(int argc, char **ar**)  

/* 獲取檔案的屬性 */

struct stat sb;

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 int main(int argc, char **ar**)  

/* 獲取檔案的屬性 */

struct stat sb;

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

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

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

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

close(fd);

/* 修改乙個字元 */

return 0;

}

先執行程序a,每隔2秒列印記憶體對映的檔案資料內容;啟動程序b,通過記憶體對映同乙個檔案並修改其資料內容,觀察程序a列印的資料資訊是否傳送變化。

2.3 匿名對映實現父子程序通訊

函式原始碼如下:

#include #include #include #include #define buf_size 100  

int main(int argc, char** ar**)

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

sleep(2);

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

return 0;

}

Linux記憶體對映 mmap

linux提供了記憶體對映函式mmap,它把檔案內容對映到一段記憶體上 準確說是虛擬記憶體上 通過對這段記憶體的讀取和修改,實現對檔案的讀取和修改,先來看一下mmap的函式宣告 原型 void mmap void addr,size t length,int prot,int flags,int f...

Linux記憶體對映 mmap函式

linux提供了記憶體對映函式mmap,它把檔案內容對映到一段記憶體上 準確說是虛擬記憶體上 通過對這段記憶體的讀取和修改,實現對檔案的讀取和修改,先來看一下mmap的函式宣告 原型 void mmap void addr,size t length,int prot,int flags,int f...

Linux記憶體對映 mmap函式

mmap將乙個檔案或者其它物件對映進記憶體。檔案被對映到多個頁上,如果檔案的大小不是所有頁的大小之和,最後乙個頁不被使用的空間將會清零。mmap在使用者空間對映呼叫系統中作用很大。標頭檔案 include函式原型void mmap void start,size t length,int prot,...