mmap() - Unix,Linux系統呼叫
廣告
名稱mmap, munmap - 將檔案或裝置對映到記憶體或取消對映概要
#include <sys/mman.h>
void *mmap(void *start, size_t length, int prot, int flags,
int fd, off_t offset);
int munmap(void *start, size_t length);
|
描述mmap() 函式請求將從檔案描述符 fd 指定的檔案(或其他物件)的偏移量 offset 開始的 length 位元組對映到記憶體中,最好對映到地址 start。 後一個地址只是一個提示,通常指定為 0。 物件實際對映到的位置由 mmap() 返回。prot 引數描述所需的記憶體保護(並且不得與檔案的開啟模式衝突)。 它要麼是 PROT_NONE,要麼是其他 PROT_* 標誌的一個或多個的按位或。
| 標籤 | 描述 |
|
PROT_EXEC | 頁面可以執行。 |
|
PROT_READ | 頁面可以讀取。 |
|
PROT_WRITE | 頁面可以寫入。 |
|
PROT_NONE | 頁面不可訪問。 |
flags 引數指定對映物件的型別、對映選項以及對頁面的對映副本所做的修改是私有的還是與其他引用共享的。 它具有位
| 標籤 | 描述 |
|
MAP_FIXED | 不要選擇與指定地址不同的地址。如果由 start 和 len 指定的記憶體區域與任何現有對映的頁面重疊,則現有對映的重疊部分將被丟棄。如果指定的地址無法使用,mmap() 將失敗。如果指定了 MAP_FIXED,則 start 必須是頁面大小的倍數。不鼓勵使用此選項。 |
|
MAP_SHARED | 與對映此物件的所有其他程序共享此對映。 向區域儲存等效於寫入檔案。在呼叫 msync(2) 或 munmap(2) 之前,檔案可能不會實際更新。 |
|
MAP_PRIVATE | 建立一個私有的寫時複製對映。 對區域的儲存不會影響原始檔案。 mmap() 呼叫後對檔案所做的更改是否在對映區域中可見是不確定的。 |
必須精確指定 MAP_SHARED 和 MAP_PRIVATE 之一。以上三個標誌在 POSIX.1-2001 中進行了描述。 Linux 還知道以下非標準標誌
| 標籤 | 描述 |
|
MAP_DENYWRITE | | | 此標誌被忽略。(很久以前,它表示嘗試寫入基礎檔案應該失敗並顯示 ETXTBUSY。但這導致了拒絕服務攻擊。) |
|
MAP_EXECUTABLE | | | 此標誌被忽略。 |
|
MAP_NORESERVE | | | 不要為此對映保留交換空間。當保留交換空間時,可以保證可以修改對映。當不保留交換空間時,如果物理記憶體不可用,則寫入時可能會出現 SIGSEGV。另請參見 proc(5) 中對檔案 /proc/sys/vm/overcommit_memory 的討論。在 2.6 之前的核心中,此標誌僅對私有可寫對映有效。 |
|
MAP_LOCKED(自 Linux 2.5.37 起) | | | 以 mlock() 的方式將對映區域的頁面鎖定到記憶體中。 在較舊的核心中,此標誌被忽略。 |
|
MAP_GROWSDOWN | | | 用於堆疊。指示核心虛擬機器系統對映應向下擴充套件到記憶體中。 |
|
MAP_ANONYMOUS | | | 對映不受任何檔案支援;fd 和 offset 引數被忽略。 自核心 2.4 起,僅在 Linux 上支援將此標誌與 MAP_SHARED 結合使用。 |
|
MAP_ANON | | | MAP_ANONYMOUS 的別名。已棄用。 |
|
MAP_FILE | | | 相容性標誌。被忽略。 |
|
MAP_32BIT | | | 將對映放入程序地址空間的前 2GB 中。設定 MAP_FIXED 時忽略。此標誌目前僅在 x86-64 的 64 位程式中受支援。 |
|
MAP_POPULATE(自 Linux 2.5.46 起) | | | 透過對檔案執行預讀來填充(預取)檔案對映的頁表。 對對映的後續訪問不會因頁面錯誤而被阻塞。 |
|
MAP_NONBLOCK(自 Linux 2.5.46 起) | | | 僅與 MAP_POPULATE 結合使用才有意義。不要執行預讀:只為 RAM 中已存在的頁面建立頁表條目。 |
某些系統記錄了附加標誌 MAP_AUTOGROW、MAP_AUTORESRV、MAP_COPY 和 MAP_LOCAL。
除非設定了 MAP_ANONYMOUS,否則 fd 應為有效的檔案描述符。如果設定了 MAP_ANONYMOUS,則在 Linux 上忽略 fd。但是,如果指定了 MAP_ANONYMOUS(或 MAP_ANON),某些實現需要 fd 為 -1,並且可移植的應用程式應確保這一點。
offset 應該是 getpagesize(2) 返回的頁面大小的倍數。 由 mmap() 對映的記憶體在 fork(2) 中保留,具有相同的屬性。 檔案以頁面大小的倍數進行對映。對於不是頁面大小倍數的檔案,對映時剩餘記憶體將清零,並且對該區域的寫入不會寫入檔案。對映的基礎檔案大小更改對對應於檔案已新增或刪除區域的頁面的影響是不確定的。 munmap() 系統呼叫刪除指定地址範圍的對映,並導致對該範圍內的地址的進一步引用生成無效的記憶體引用。程序終止時,該區域也會自動取消對映。另一方面,關閉檔案描述符不會取消對映該區域。 地址 start 必須是頁面大小的倍數。包含指示範圍一部分的所有頁面都被取消對映,隨後對這些頁面的引用將生成 SIGSEGV。如果指示的範圍不包含任何對映的頁面,則不會出錯。 對於檔案支援的對映,對映檔案的 st_atime 欄位可以在 mmap() 和相應的取消對映之間隨時更新;對對映頁面的第一次引用將更新該欄位(如果尚未更新)。 使用 PROT_WRITE 和 MAP_SHARED 對映的檔案的 st_ctime 和 st_mtime 欄位將在寫入對映區域後以及在隨後的 msync()(使用 MS_SYNC 或 MS_ASYNC 標誌)之前更新,如果發生這種情況的話。 返回值成功時,mmap() 返回指向對映區域的指標。出錯時,返回 MAP_FAILED 值(即 (void *) -1),並相應地設定 errno。成功時,munmap() 返回 0,失敗時返回 -1,並設定 errno(可能設定為 EINVAL)。註釋PROT_READ 是否包含 PROT_EXEC 取決於體系結構。可移植程式應始終設定 PROT_EXEC,如果他們打算在新對映中執行程式碼。錯誤
| 標籤 | 描述 |
|
EACCES | 檔案描述符引用非規則檔案。或者請求了 MAP_PRIVATE,但 fd 未開啟以供讀取。或者請求了 MAP_SHARED 並設定了 PROT_WRITE,但 fd 未以讀/寫 (O_RDWR) 模式開啟。或者設定了 PROT_WRITE,但檔案是僅追加的。 |
|
EAGAIN | 檔案已被鎖定,或者鎖定了太多記憶體(參見 setrlimit(2))。 |
|
EBADF |
fd 不是有效的檔案描述符(並且未設定 MAP_ANONYMOUS)。 |
|
EINVAL | 我們不喜歡 start、length 或 offset。(例如,它們太大,或者未對齊到頁面邊界。) |
|
ENFILE | 已達到開啟檔案的系統總數量限制。 |
|
ENODEV | 指定檔案的底層檔案系統不支援記憶體對映。 |
|
ENOMEM | 沒有可用的記憶體,或者程序的最大對映數將超過。 |
|
EPERM | prot 引數請求 PROT_EXEC,但對映區域屬於已安裝為 no-exec 的檔案系統上的檔案。 |
|
ETXTBSY | | |
設定了 MAP_DENYWRITE,但 fd 指定的物件已開啟以供寫入。 |
| 使用對映區域可能會導致這些訊號 |
|
SIGSEGV | | | 嘗試寫入對映為只讀的區域。 |
|
SIGBUS | 嘗試訪問緩衝區中不對應於檔案的部分(例如,超過檔案末尾,包括另一個程序已截斷檔案的情況)。 |
可用性在提供 mmap()、msync() 和 munmap() 的 POSIX 系統上,在 <unistd.h> 中將 _POSIX_MAPPED_FILES 定義為大於 0 的值。(另請參見 sysconf(3)。)符合標準SVr4、4.4BSD、POSIX.1-2001。錯誤在 Linux 上,沒有上面 MAP_NORESERVE 下建議的保證。預設情況下,當系統記憶體不足時,任何程序都可能隨時被終止。在 2.6.7 之前的核心中,MAP_POPULATE 標誌僅在 prot 指定為 PROT_NONE 時才有效。 另請參見
B.O. Gallmeister,《POSIX.4》,O’Reilly,第 128-129 頁和 389-391 頁。
廣告
|