在C/C++ 中常用的內存分配和管理的方式有很多,如智能指針, STL容器, new/delete, malloc/free, brk, sbrk等等,最近研究了一下Unix比較底層的一種內存管理方式mmap/munmap,需要完全自己來維護分配的虛擬內存,沒有任何其他輔助的數據結構來幫助維護內存空間,但其優點就是效率比其他的內存分配方式要高。
一、在終端里輸入 man mmap 可以查看此函數的API文檔,此函數的具體描述如下:
void *mmap(void *start,size_t length,int prot,int flags,int fd,off_t offsize);
具體參數含義
start : 指向欲映射的內存起始地址,通常設為 NULL,代表讓系統自動選定地址,映射成功后返回該地址。
length: 代表將文件中多大的部分映射到內存。
prot : 映射區域的保護方式。可以為以下幾種方式的組合:
PROT_EXEC 映射區域可被執行
PROT_READ 映射區域可被讀取
PROT_WRITE 映射區域可被寫入
PROT_NONE 映射區域不能存取
flags : 影響映射區域的各種特性。在調用mmap()時必須要指定MAP_SHARED 或MAP_PRIVATE。
MAP_FIXED 如果參數start所指的地址無法成功建立映射時,則放棄映射,不對地址做修正。通常不鼓勵用此旗標。
MAP_SHARED 對映射區域的寫入數據會復制回文件內,而且允許其他映射該文件的進程共享。
MAP_PRIVATE 對映射區域的寫入操作會產生一個映射文件的復制,即私人的“寫入時復制”(copy on write)對此區域作的任何修改都不會寫回原來的文件內容。
MAP_ANONYMOUS建立匿名映射。此時會忽略參數fd,不涉及文件,而且映射區域無法和其他進程共享。
MAP_DENYWRITE只允許對映射區域的寫入操作,其他對文件直接寫入的操作將會被拒絕。
MAP_LOCKED 將映射區域鎖定住,這表示該區域不會被置換(swap)。
fd : 要映射到內存中的文件描述符。如果使用匿名內存映射時,即flags中設置了MAP_ANONYMOUS,fd設為-1。有些系統不支持匿名內存映射,則可以使用fopen打開/dev/zero文件,
然后對該文件進行映射,可以同樣達到匿名內存映射的效果。
offset:文件映射的偏移量,通常設置為0,代表從文件最前方開始對應,offset必須是PAGE_SIZE的整數倍。
返回值:
若映射成功則返回映射區的內存起始地址,否則返回MAP_FAILED(-1),錯誤原因存于errno 中。
錯誤代碼:
EBADF 參數fd 不是有效的文件描述詞
EACCES 存取權限有誤。如果是MAP_PRIVATE 情況下文件必須可讀,使用MAP_SHARED則要有PROT_WRITE以及該文件要能寫入。
EINVAL 參數start、length 或offset有一個不合法。
EAGAIN 文件被鎖住,或是有太多內存被鎖住。
ENOMEM 內存不足。
用戶層的調用很簡單,其具體功能就是直接將物理內存直接映射到用戶虛擬內存,使用戶空間可以直接對物理空間操作。但是對于內核層而言,其具體實現比較復雜。
二、例子程序如下
我是在64位的Mac OS X系統下編譯運行的,64位系統內存頁的大小為8k, 32位為4k
上一篇 C++ Singleton
下一篇 二進制加法