2014-02-25 48 views
4

我正在重新學習C++,並且需要使用內存映射文件。我決定使用boost(因爲它似乎是堅實的庫)。在Linux上增強內存映射文件歸零

我創建了一個內存映射文件映射到一個雙精度數組,並寫在這個數組中的第一個double。磁盤文件包含前四個字節中的一些數據,其餘部分歸零,這對我來說很好奇,因爲通常如果我在C++中獲取指向內存位置的指針,在大多數情況下,我必須假定它包含垃圾。

我有任何保證新創建的內存映射文件將被清零(至少在Linux上)?我沒有找到任何參考。

BOOST_AUTO_TEST_CASE(OpenMMapFile){ 

boost::iostreams::mapped_file file; 

boost::iostreams::mapped_file_params params; 

params.path = "/tmp/mmaptest-1"; 
params.mode = std::ios::in | std::ios::out; 
params.new_file_size = 10*sizeof(double); 

file.open(params); 

double* data = static_cast<double*>((void*)file.data()); 

data[0] = 12; 

file.close(); 

} 

下面是該文件的內容:

cat /tmp/mmaptest-1 | base64 
AAAAAAAAKEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA =

編輯

由於@Zan指出---提高實際使用ftruncate來調整mmaped文件,所以調零保證(至少在Linux上)。

+1

在Unix/Linux操作系統已經提供了安全保證數據不被泄露,因此當存儲器中的文件或區域被分配一定不能讓一個進程看到以前的文件究竟是什麼磁盤/內存/處理。滿足這一保證的最簡單方法是清零內存。所以這就是它的作用。 –

+0

richard是比較linux到Windows95? – 2015-04-21 19:19:58

回答

3

內存映射文件包含文件中的內容。

如果它是一個新文件,它已被擴展到正確的大小,擴展名將包含零。擴展文件通常使用ftruncate函數完成。

的ftruncate手冊頁說:

If the file previously was larger than this size, the extra data is 
    lost. If the file previously was shorter, it is extended, and the 
    extended part reads as null bytes ('\0'). 

所以,是的,零擔保。

-1

我認爲boost會爲您調整文件以實現映射地址空間真正由磁盤空間而不是稀疏文件備份。 這很慢,特別是如果你想在前面創建一個大的地址空間, 可能永遠不會被完全使用 - 這樣你就可以在這個地址空間中分配很多對象。 他們正在這樣做,因爲在寫入內存映射稀疏文件(忽略像setjmp/longjmp這樣的病態解決方案)時,UNIX上沒有可用的方法來處理磁盤空間不足。 但是你仍然有其他進程截斷文件的可能性, 在這種情況下,前面提到的問題再次擡頭。

不幸的是,他們也正在做這個(分配磁盤空間相匹配的地址空間的大小,而不是使用稀疏文件)在Windows上,其中結構化異常處理的存在。

+0

這是不真實的,因爲它是在這個問題中建立的:http://stackoverflow.com/q/26682229/7918,實際上磁盤空間並未預先分配! –

+0

當我最後一次嘗試時,進入增強庫的匹配調用很長時間。這可能會改變,但我懷疑它,因爲提到的問題仍然存在。 – 2015-04-21 19:17:55

+0

我剛試過這個,並且調用boost來創建一個託管內存映射文件並在其中分配一個大對象,立即返回。這意味着,在創建文件或分配對象時不會分配磁盤空間。這意味着,有人冒着SIGSEGV的風險。請參閱mmap的手冊頁。 – 2015-04-21 19:56:41