我正在對可以卸載的文件執行mmap()(該文件位於用戶可以隨時移除的USB設備上),以及我的應用程序崩潰,如果文件被卸載,然後我嘗試訪問緩衝區中的任何元素。在卸載的文件上執行mmap()後避免崩潰
對此的任何解決方案?
我正在對可以卸載的文件執行mmap()(該文件位於用戶可以隨時移除的USB設備上),以及我的應用程序崩潰,如果文件被卸載,然後我嘗試訪問緩衝區中的任何元素。在卸載的文件上執行mmap()後避免崩潰
對此的任何解決方案?
請勿訪問不可用的文件。檢查文件是否仍然存在,或使用無法卸載的文件。
最簡單的事情就是設置一個信號處理程序,用於檢查對應於mmap
編址的存儲器位置的訪問。
你會使用sigaction
形式的信號處理程序,而不是簡單的signal
處理器爲sigaction
處理對應於信號的地址struct __siginfo *
參數接收信息。可以檢查它是否位於mmap
ed文件的地址範圍內。
mmap
當你不想處理緩衝區讀/寫數據的複雜性,但是由於出錯而只能得到一種形式的錯誤(信號)時,它非常棒。通過read
/write
機制,您可以獲得errno
並確定發生了什麼。在這種情況下,它非常適合開發者。
要跳轉到一個位置接收到信號後,那麼你就需要利用setjmp
和longjmp
/siglongjmp
的 - 看到this question
首先是一些使用此,我想說這應該作爲一個很好的參數不要使用mmap
不必要地作爲「優化讀取」或類似。除了設備移除之外,其他進程的文件截斷等問題可能會導致訪問錯誤SIGBUS
。
如果確實需要使用mmap
,則可以安裝SIGBUS
的信號處理程序。它的任務應該主要是爲了:
SIGBUS
發生了全球性(或線程本地,如果你的程序是多線程)標誌,所以出錯的代碼可以做到心中有數。mmap
與MAP_FIXED
可以在錯誤頁面頂部映射一個新的匿名頁面。可選填寫訪問地圖的代碼將被識別爲錯誤的數據;這可能會導致第1步不必要。另一種方法是設置一個全球性的(或者線程本地)訪問地圖前jmp_buf
,並且已經在信號處理程序只需調用longjmp
。
注意,無論是mmap
也不longjmp
是異步信號安全的,但有問題的SIGBUS
不是異步信號(儘管它應該算得上一個,如果斷裂訪問發生在非異步信號安全庫內功能如sscanf
)。只要它是你自己的代碼,而不是庫函數,訪問地圖,你就應該安全。並且mmap
在大多數/所有現實世界的實現中都是異步信號安全的,因此即使它在形式上不正確,您也應該在實踐中使用第一種解決方案。
會這樣說:對於'mmap'來說更多的不是滿足眼睛 - 因爲錯誤處理比傳統的I/O要複雜得多。這不一定是一個理由_against using_'mmap' ...只是意識到你召喚的精神;-) –
並確保他們不會飛出你的鼻子.. :-) –
您可以通過使用http://linux.die.net/man/7/inotify來獲得關於文件,目錄中的任何更改的通知。 你可以考慮使用IN_DELETE。
這些通知將是立即因爲OP試圖遏制的頁面錯誤?如果沒有,請不要打擾。 –
看來你必須調用'read()'來查明是否有任何改變,但是在'read()'沒有返回任何興趣和下面的內存訪問之間可能發生改變。這是一個競賽條件。此外,事件隊列可能會溢出。所以,這不是一個解決方案。 –
由於可能的競賽條件,我不認爲這是非常有用的。圍繞訪問映射區域的代碼期望並捕獲「SIGBUS」會有幫助嗎?或者類似的東西? –
編號'SIGBUS'不一定是可恢復的,儘管一些實現在從處理程序返回後重試錯誤指令。 –
@SimonRichter你不需要重試錯誤指令,你只需要確定你不能繼續讀/寫,之後你停止嘗試訪問區域並返回給調用者一些錯誤指示。也許'setjmp()'/'longjmp()'可以避免重新執行錯誤指令。 –