簡體   English   中英

快速調整mmap文件的大小

[英]Fast resize of a mmap file

我需要一個非常大的mmap文件的無副本重新大小,同時仍然允許並發訪問讀取器線程。

簡單的方法是在同一個文件中使用兩個MAP_SHARED映射(增長文件,然后創建包含增長區域的第二個映射),然后在所有可以訪問它的讀者完成后取消映射舊映射。 但是,我很好奇下面的方案是否有效,如果有的話,它是否有任何優勢。

  1. 使用MAP_PRIVATE mmap一個文件
  2. 在多個線程中對此內存進行只讀訪問
  3. 獲取文件的互斥鎖,寫入內存(假設這是以讀者可能正在讀取內存的方式完成的,不會被它搞砸)
  4. 或獲取互斥鎖,但增加文件的大小並使用mremap將其移動到新地址(調整映射大小而不復制或不必要的文件IO。)

瘋狂的部分出現在(4)。 如果移動內存,舊地址將變為無效,仍在閱讀內容的讀者可能會突然發生訪問沖突。 如果我們修改讀取器以捕獲此訪問沖突然后重新啟動操作(即不重新讀取錯誤地址,重新計算給定偏移量的地址和mremap中的新基址),該怎么辦。是的我知道這是邪惡的但是在我看來,讀者只能成功讀取舊地址的數據,或者因訪問沖突而失敗並重試。 如果采取足夠的謹慎措施,那應該是安全的。 由於重新調整大小不會經常發生,讀者最終會成功並且不會陷入重試循環。

如果在讀取器仍具有指向它的指針時重新使用舊地址空間,則可能會出現問題。 然后將沒有訪問沖突,但數據將是不正確的,並且程序進入不確定行為的獨角獸和糖果填充的土地(其中通常既沒有獨角獸也沒有糖果。)

但是如果你完全控制了分配並且可以確定在此期間發生的任何分配都不會重復使用那個舊的地址空間,那么這不應該是一個問題,並且行為不應該是未定義的。

我對嗎? 這可行嗎? 使用兩個MAP_SHARED映射是否有任何優勢?

我很難想象一個你不知道文件大小的上限的情況。 假設這是真的,您可以通過在首次使用mmap()映射文件時提供該大小來“保留”地址空間以獲得文件的最大大小。 當然,超出文件實際大小的任何訪問都會導致訪問沖突,但這就是你希望它的工作方式 - 你可以爭辯說保留額外的地址空間可以確保訪問沖突而不是讓地址范圍保持開放被其他調用用於mmap()或malloc()之類的東西。

無論如何,關鍵在於我的解決方案,你永遠不會移動地址范圍,你只改變它的大小,現在你的鎖定是圍繞為每個線程提供當前有效大小的數據結構。

如果您有這么多文件,每個文件的最大映射會使您超出地址空間,我的解決方案不起作用,但這是64位地址空間的年齡,所以希望您的最大映射大小沒有問題。

(只是為了確保我沒有忘記一些愚蠢的東西,我確實寫了一個小程序來說服自己創建大於文件大小的映射,當你試圖超出文件大小訪問時會產生訪問沖突,然后工作正常一旦你ftruncate()文件變大,所有從第一個mmap()調用返回的地址都相同。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM