2012-11-05 83 views
2

前提是:mmap是否連續分配堆內存?

  • 大小我請求的頁面大小
  • 起始地址我要求的倍數的大小+啓動最後一個分配

的地址,如果我公司始終遵循這些規則使用mmap在堆上分配內存時,返回的地址是否連續?或者他們之間可能存在差距?

+1

在哪個操作系統?這些東西取決於操作系統。 –

+0

如果它不是獨立於操作系統的,那麼我假設我的問題的答案是「否」,因爲我想編寫可移植代碼。 – Matt

+0

「便攜」是一個非常廣泛的術語。 –

回答

2

快速答案:不一定。在有限的各種機器上進行廣泛的測試時,它幾乎總是能夠工作的一個很好的機會,但它絕對不是好的做法。大多數Linux都支持MAP_FIXED標誌,但在我的經驗中也是有問題的。避免。

你的情況更好

是簡單地分配你需要在一次的一切,然後手動分配指針映射的每個子段:

int LengthOf_FirstThing = 0x18000; 
int LengthOf_SecondThing = 0x10100; 
int LengthOf_ThirdThing = 0x20000; 

int _pagesize = getpagesize(); 
int _pagemask = _pagesize - 1; 

size_t sizeOfEverything = LengthOf_FirstThing + LengthOf_SecondThing + LengthOf_ThirdThing; 
sizeOfEverything = (sizeOfEverything + _pagemask) & ~(_pagemask); 

int8_t* result = (int8_t*)mmap(nullptr, sizeOfEverything, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 
int8_t* myFirstThing = result; 
int8_t* mySecondThing = myFirstThing + LengthOf_FirstThing; 
int8_t* myThirdThing = mySecondThing + LengthOf_SecondThing; 

這種方法的優點還在於每個東西您的映射不必嚴格對齊頁面大小。最重要的是,它保證了充分的連續記憶。

更長的回答: mmap()的實現可以完全自由地忽略'提示'地址,所以你永遠不應該期望地址被尊重。這可能比預期更普遍,因爲某些實現可能實際上不支持新mmap()的頁面大小。他們可能會將有效起始地圖限制爲16k或64k邊界,以幫助減少管理非常大的虛擬地址空間所需的開銷。這樣的實現總是會忽視不與這種邊界對齊的mmap()提示。

此外,mmap()根本不會從堆中分配內存。堆是創建進程時由C運行時庫(glibc on * nix)創建/保留的內存區域。 malloc()和new/delete通常是從堆中提取的唯一函數,以及任何可能在內部使用malloc/new的庫。堆本身通常由內部調用mmap()來創建和管理。

1

我認爲這不是指定的,而是所謂的「實現細節」。即你不應該依賴於一種行爲或另一種行爲,而是假設指針是不透明的並且不關心它的確切值。

(這就是說,有可能是黑客的地方和時間。在這種情況下,你需要找出你的操作系統究竟如何運行。)

3

你可以得到你想要用MAP_FIXED標誌的行爲。不幸的是,對於你的目標,這不是普遍支持,所以你想檢查返回值,以確保它給你你請求的分配。爲了便於攜帶,您需要一個備份計劃,以便在通話返回0時返回0.