**:
linux
中的兩種共享記憶體。一種是我們的ipc通訊system v版本的共享記憶體,另外的一種就是我們今天提到的儲存對映i/o(mmap函式)
在說mmap之前我們先說一下普通的讀寫檔案的原理,程序呼叫read或是write後會陷入核心,因為這兩個函式都是系統呼叫,進入系統呼叫後,核心開始讀寫檔案,假設核心在讀取檔案,核心首先把檔案讀入自己的核心空間,讀完之後程序在核心回歸使用者態,核心把讀入核心記憶體的資料再copy進入程序的使用者態記憶體空間。實際上我們同一份檔案內容相當於讀了兩次,先讀入核心空間,再從核心空間讀入使用者空間。
linux提供了記憶體對映函式mmap, 它把檔案內容對映到一段記憶體上(準確說是虛擬記憶體上), 通過對這段記憶體的讀取和修改, 實現對檔案的讀取和修改,mmap()系統呼叫使得程序之間可以通過對映乙個普通的檔案實現共享記憶體。普通檔案對映到程序位址空間後,程序可以向訪問記憶體的方式對檔案進行訪問,不需要其他系統呼叫(read,write)去操作。
mmap圖示例:
這就是mmap系統呼叫的介面,mmap函式成功返回指向記憶體區域的指標,圖上的程序的位址空間的開始位址就是mmap函式的返回值,失敗返回map_failed。
addr,某個特定的位址作為起始位址,當被設定為null,系統會在位址空間選擇一塊合適的記憶體區域。
length說的是記憶體段的長度。
prot是用來設定記憶體段的訪問許可權。
prot引數
說明prot_read
記憶體段可讀
prot_write
記憶體段可寫
prot_exec
記憶體段可執行
prot_none
記憶體段不能被訪問
flags引數控制記憶體段內容被修改以後程式的行為。
flags引數
說明map_shared
程序間共享記憶體,對該記憶體段修改反映到對映檔案中。提供了posix共享記憶體
map_private
記憶體段為呼叫程序所私有。對該記憶體段的修改不會反映到對映檔案
map_annoymous
這段記憶體不是從檔案對映而來的。內容被初始化為全0
map_fixed
記憶體段必須位於start引數指定的位址處,start必須是頁大小的整數倍(4k整數倍)
map_hugetlb
按照大記憶體頁面來分配記憶體空間
fd引數是用來被對映檔案對應的檔案描述符。通過open系統呼叫得到。offset設定從何處進行對映。
mmap使用注意事項:
利用mmap進行非血緣程序間通訊**:
[cpp]view plain
copy
#include
#include
#include
#include
#include
#include
#include
#include
struct
stu
; int
main(
intargc,
char
*argv)
//這個程序用於建立對映區進行寫。
struct
stu student = ;
intfd = open(argv[1],o_rdwr|o_creat|o_trunc,0644);
if(fd
ftruncate(fd,sizeof
(struct
stu));
//檔案拓展大小。
struct
stu *p = (
struct
stu*)mmap(null,
sizeof
(struct
stu),prot_read|prot_write,map_shared,fd,0);
//建立乙個結構體大小的共享對映區。共享對映區我們可以當做陣列區看待。
if(p == map_failed)
close(fd); //關閉不用的檔案描述符。
while
(1)
intret = munmap(p,
sizeof
(student));
if(ret
return
0;
}[cpp]view plain
copy
#include
#include
#include
#include
#include
#include
#include
struct
stu
; int
main(
intargc,
char
*argv)
//這個程序讀
intfd = open(argv[1],o_rdonly,0644);
if(fd
struct
stu student;
struct
stu *p = (
struct
stu*)mmap(null,
sizeof
(struct
stu),prot_read,map_shared,fd,0);
if(p == map_failed)
close(fd);
inti = 0;
while
(1)
intret = munmap(p,
sizeof
(student));
if(ret
return
0;
} **截圖:
分析:因為只建立乙個結構體大小的共享記憶體,後面寫入的資料把前面寫入的資料覆蓋了。
shm圖示例:
(1)通過int shmget(key_t key, size_t size, int shm***);在物理記憶體建立乙個共享記憶體,返回共享記憶體的編號。
(2)通過void *shmat(int shmid, constvoid shmaddr,int shm***);連線成功後把共享記憶體區物件對映到呼叫程序的位址空間
(3)通過void *shmdt(constvoid* shmaddr);斷開使用者級頁表到共享記憶體的那根箭頭。
(4)通過int shmctl(int shmid, int cmd, struct shmid_ds* buf);釋放物理記憶體中的那塊共享記憶體。
總結mmap和shm:
1、mmap是在磁碟上建立乙個檔案,每個程序位址空間中開闢出一塊空間進行對映。
而對於shm而言,shm每個程序最終會對映到同一塊物理記憶體。shm儲存在物理記憶體,這樣讀寫的速度要比磁碟要快,但是儲存量不是特別大。
2、相對於shm來說,mmap更加簡單,呼叫更加方便,所以這也是大家都喜歡用的原因。
3、另外mmap有乙個好處是當機器重啟,因為mmap把檔案儲存在磁碟上,這個檔案還儲存了作業系統同步的映像,所以mmap不會丟失,但是shmget就會丟失。
mmap記憶體對映區和shm共享記憶體的區別
linux中的兩種共享記憶體。一種是我們的ipc通訊system v版本的共享記憶體 shm 另外的一種就是記憶體對映i o mmap函式 1.mmap記憶體對映 記憶體對映是通過操作記憶體來實現對檔案的操作,這樣可以加快執行速度,不是專門用來進行資料通訊的 但它也可以用於程序間的通訊 2.shm共...
mmap對映區和shm共享記憶體的區別總結
linux 中的兩種共享記憶體。一種是我們的ipc通訊system v版本的共享記憶體,另外的一種就是我們今天提到的儲存對映i o mmap函式 在說mmap之前我們先說一下普通的讀寫檔案的原理,程序呼叫read或是write後會陷入核心,因為這兩個函式都是系統呼叫,進入系統呼叫後,核心開始讀寫檔案...
mmap共享記憶體對映實戰
mmap函式用於申請一段記憶體空間。我們可以將這一段記憶體空間作為程序之間通訊的共享記憶體也可以將檔案直接對映其中。munmap函式則釋放由mmap函式建立的這段記憶體空間。函式定義如下 include void mmap void addr,size t length,int prot,int f...