簡體   English   中英

內存映射文件讀取輸入文件的安全性如何?

[英]How safe are memory-mapped files for reading input files?

將輸入文件映射到存儲器然后直接從映射的存儲器頁面解析數據可以是從文件讀取數據的方便且有效的方式。

但是,除非您可以確保沒有其他進程寫入映射文件,否則這種做法似乎從根本上說是不安全的,因為即使私有只讀映射中的數據可能會在另一個進程寫入基礎文件時發生更改。 (POSIX例如,未指定 “在建立MAP_PRIVATE映射后是否通過MAP_PRIVATE映射可以看到對基礎對象的修改”。)

如果您希望在對映射文件進行外部更改時使代碼安全,則必須僅通過易失性指針訪問映射內存,然后非常小心您如何讀取和驗證輸入,這似乎不切實際。許多用例。

這個分析是否正確? 內存映射API的文檔通常只在傳遞中提到這個問題,如果有的話,所以我想知道我是否遺漏了一些東西。

這不是一個真正的問題。

是的,另一個進程可能會在您映射文件時修改該文件,是的,您可能會看到修改。 甚至可能 ,因為幾乎所有的操作系​​統都有統一的虛擬內存系統,所以除非有人請求無緩沖的寫入,否則沒有辦法在沒有經過緩沖區緩存的情況下進行編寫,沒有辦法讓沒有人拿着映射看到變化。
這甚至都不是壞事。 其實,如果你無法看到的變化會更令人不安。 由於文件准映射時會成為地址空間的一部分,因此您可以看到文件的更改。

如果您使用傳統的I / O(例如read ),有人仍然可以在您閱讀時修改該文件。 換句話說, 在存在修改的情況下將文件內容復制到內存緩沖區並不總是安全的 它是“安全的”,因為read不會崩潰,但它不能保證您的數據是一致的。
除非您使用readv ,否則您無法保證原子性(即使使用readv您也無法保證內存中的內容與磁盤上的內容一致,或者在兩次調用readv之間不會發生變化)。 有人可能會在兩次read操作之間修改文件,或者甚至在您處於中間時修改文件。
只是一些沒有被正式保證,但“可能仍然有效” -相反,例如在Linux下寫的demonstrably不是原子。 甚至不是偶然的。

好消息:
通常,進程只是打開任意隨機文件並開始寫入它。 當發生這樣的事情時,它通常是屬於進程的眾所周知的文件(例如日志文件),或者是您明確告訴進程寫入的文件(例如,保存在文本編輯器中),或者進程創建一個新文件(例如編譯器創建一個目標文件),或者該過程僅附加到現有文件(例如db日志,當然還有日志文件)。 或者,進程可能會自動將文件替換為另一個文件(或取消鏈接)。

在每種情況下,整個可怕的問題歸結為“沒有問題”,因為要么你很清楚會發生什么(所以這是你的責任),要么它無縫地工作而不會干擾。

如果你真的不喜歡另一個進程可能可能寫入文件,而你把它映射的可能性,你可以簡單地忽略FILE_SHARE_WRITE當您創建的文件句柄在Windows下。 POSIX使它更復雜,因為您需要為強制鎖定fcntl描述符,這在每個系統上都不是必需的,或者是100%可靠的(例如,在Linux下)。

理論上,如果有人在您閱讀文件時修改文件,您可能會遇到麻煩。 在實踐中:你正在閱讀角色,沒有別的東西:沒有指針,或任何可能讓你陷入困境的東西。 在實踐中...正式地說,我認為它仍然是未定義的行為,但它是我認為你不必擔心的行為。 除非修改非常小,否則會遇到很多編譯器錯誤,但這就是它的結束。

可能導致問題的一個案例是文件縮短了。 我不確定當你讀到最后時會發生什么。

最后:系統不是隨意打開和修改文件。 這是一個源文件; 這將是一些做這件事的白痴程序員,他應得的。 在任何情況下,您的未定義行為都不會破壞系統或其他人的文件。

另請注意,大多數編輯都在私人副本上工作; 回寫時,他們通過重命名原始文件並創建新文件來實現。 在Unix下,一旦你打開文件來mmap它,所有重要的是inode號。 當編輯器重命名或刪除文件時,您仍然保留副本。 修改后的文件將獲得一個新的inode。 您唯一需要擔心的是,如果有人打開文件進行更新,然后繼續修改它。 沒有多少程序在文本文件上執行此操作,除了向末尾添加其他數據。

因此,雖然正式,但存在一些風險,我認為你不必擔心它。 (如果你真的是偏執狂,那么你可以在你編寫mmap關閉寫入授權。如果真的有一個敵方特工要拿你的,他可以把它重新打開。)

暫無
暫無

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

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