2013-07-22 63 views
5

我剛剛有一個令人驚訝的錯誤,其中使用LoadLibrary API調用加載的DLL文件在加載時被重命名。顯然,在一個文件上有一個開放的DLL句柄並不能阻止該文件被重命名,甚至不能移動到另一個路徑。但是,它可以防止刪除並移動到其他磁盤。如果發生這種情況,使用DLL 的程序繼續正常工作。 ProcessExplorer顯示DLL的處理路徑相應地更新。爲什麼打開的DLL句柄不能保護文件不被移動?

此行爲與Windows中的普通文件句柄不同。例如,當對同一個DLL保留開放的std::ifstream時,操作系統不再允許重命名。我發現這種行爲令人驚訝,並想知道是否有人可以給出解釋?特別是我會對允許這樣做的基本原理感興趣,因爲我認爲追蹤磁盤上的文件比將其鎖定就位更困難。所以操作系統可能必須積極支持這個功能,這意味着必須有一個用例呢?

回答

6

這不是一個錯誤。 LoadLibrary使用File Mapping來訪問文件。雖然您有一個文件的映射部分,但它不能被刪除(或移動到另一個磁盤)。看起來LoadLibrary關閉了一個文件句柄(它不是必需的),並且只使用了映射部分的句柄,所以你可以自由地重命名文件但不能刪除它。

另一方面,std::ifstream使用文件句柄來訪問文件。並且它不會設置重命名和刪除操作所需的共享訪問FILE_SHARE_DELETE

實際上沒有特殊的磁盤上文件的跟蹤。文件句柄指向文件,這就是全部。打開文件並獲得句柄後,文件可以重命名或甚至刪除,並且您仍然可以訪問該文件(如果該文件已被刪除,則爲有限訪問,但您可以取消刪除文件並具有完全訪問權限) 。

+0

這很有道理。事實上,加載後關閉dll上的文件句柄,只有內存映射持續存在。還要感謝將'FILE_SHARE_DELETE'作爲['CreateFile']的選項(http://msdn.microsoft.com/zh-cn/library/windows/desktop/aa363858%28v=vs.85%29.aspx) ,我之前沒有意識到這個選擇。 – ComicSansMS

相關問題