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 | | 用於堆疊。指示核心 VM 系統對映應在記憶體中向下擴充套件。 |
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 系統上,_POSIX_MAPPED_FILES 在 <unistd.h> 中定義為大於 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 頁。
廣告
|