1. 程式人生 > >Linux中的mmap函式

Linux中的mmap函式

1,mmap函式功能
mmap函式為記憶體對映函式。負責把檔案內容對映到程序的虛擬記憶體空間, 通過對這段記憶體的讀取和修改,來實現對檔案的讀取和修改,而不需要再呼叫read,write等操作。
注意:mmap將一個檔案或者其它物件對映進記憶體。檔案被對映到多個頁上,如果檔案的大小不是所有頁的大小之和,最後一個頁不被使用的空間將會清零。mmap在使用者空間對映呼叫系統中作用很大。

2,mmap函式標頭檔案和函式原型

標頭檔案:#include<sys/mmap.h>
函式原型:void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
3,引數說明
addr:對映區的開始地址,設定為0時表示由系統決定對映區的起始地址(通常設定為NULL)
length:對映區的長度(對映到記憶體的檔案長度)。//長度單位是位元組,不足一記憶體頁按一記憶體頁處理
prot:期望的記憶體保護標誌(對映區的保護方式),不能與檔案的開啟模式衝突。是以下的某個值,可以通過“或運算”合理地組合在一起PROT_EXEC //頁內容可以被執行
PROT_READ //頁內容可以被讀取
PROT_WRITE //頁可以被寫入
PROT_NONE //頁不可訪問
flags:對映區的特性(指定對映物件的型別,對映選項和對映頁是否可以共享。它的值可以是一個或者多個以下位的組合體)
MAP_FIXED //使用指定的對映起始地址,如果由addr和length引數指定的記憶體區重疊於現存的對映空間,重疊部分將會被丟棄。如果指定的起始地址不可用,操作將會失敗。並且起始地址必須落在頁的邊界上。
MAP_SHARED //寫入對映區的資料會複製迴文件, 且允許其他對映該檔案的程序共享。與其它所有對映這個物件的程序共享對映空間。對共享區的寫入,相當於輸出到檔案。直到msync()或者munmap()被呼叫,檔案實際上不會被更新。
MAP_PRIVATE //對對映區的寫入操作會產生一個對映區的複製(copy-on-write), 對此區域所做的修改不會寫回原檔案。(建立一個寫入時拷貝的私有對映。記憶體區域的寫入不會影響到原檔案。這個標誌和以上標誌是互斥的,只能使用其中一個。)
MAP_DENYWRITE //這個標誌被忽略。
MAP_EXECUTABLE //同上
MAP_NORESERVE //不要為這個對映保留交換空間。當交換空間被保留,對對映區修改的可能會得到保證。當交換空間不被保留,同時
記憶體不足,對對映區的修改會引起段違例訊號。
MAP_LOCKED //鎖定對映區的頁面,從而防止頁面被交換出記憶體。
MAP_GROWSDOWN //用於堆疊,告訴核心VM系統,對映區可以向下擴充套件。
MAP_ANONYMOUS //匿名對映,對映區不與任何檔案關聯。
MAP_ANON //MAP_ANONYMOUS的別稱,不再被使用。
MAP_FILE //相容標誌,被忽略。
MAP_32BIT //將對映區放在程序地址空間的低2GB,MAP_FIXED指定時會被忽略。當前這個標誌只在x86-64平臺上得到支援。
MAP_POPULATE //為檔案對映通過預讀的方式準備好頁表。隨後對對映區的訪問不會被頁違例阻塞。
MAP_NONBLOCK //僅和MAP_POPULATE一起使用時才有意義。不執行預讀,只為已存在於記憶體中的頁面建立頁表入口。
fd由open函式返回的檔案描述符, 代表要對映的檔案。其值也可以設定為-1,此時需要指定flags引數中的MAP_ANON,表明進行的是匿名對映。
offset被對映物件內容的起點(以檔案開始處的偏移量, 必須是分頁大小的整數倍, 通常為0, 表示從檔案頭開始對映。
4,返回型別
成功執行時,mmap()返回被對映區的返回0。失敗時,mmap()返回MAP_FAILED[其值為(void *)-1],munmap返回-1。errno被設為以下的某個值
EACCES:訪問出錯
EAGAIN:檔案已被鎖定,或者太多的記憶體已被鎖定
EBADF:fd不是有效的檔案描述詞
EINVAL:一個或者多個引數無效
ENFILE:已達到系統對開啟檔案的限制
ENODEV:指定檔案所在的檔案系統不支援記憶體對映
ENOMEM:記憶體不足,或者程序已超出最大記憶體對映數量
EPERM:權能不足,操作不允許
ETXTBSY:已寫的方式開啟檔案,同時指定MAP_DENYWRITE標誌
SIGSEGV:試著向只讀區寫入
SIGBUS:試著訪問不屬於程序的記憶體區
5,系統呼叫
mmap()系統呼叫使得程序之間通過對映同一個普通檔案實現共享記憶體。普通檔案被對映到程序地址空間後,程序可以像訪問普通記憶體一樣對檔案進行訪問,不必再呼叫read(),write()等操作。
  注:實際上,mmap()系統呼叫並不是完全為了用於共享記憶體而設計的。它本身提供了不同於一般對普通檔案的訪問方式,程序可以像讀寫記憶體一樣對普通檔案的操作。而Posix或System V的共享記憶體IPC則純粹用於共享目的,當然mmap()實現共享記憶體也是其主要應用之一。