2008-10-23 111 views
2

我的磁盤上有一個單獨的分區,格式化爲FAT32。當我休眠Windows時,我希望能夠加載另一個操作系統,創建/修改該分區上的文件,然後使Windows退出休眠狀態,並能夠看到我所做的更改。強制Windows刷新磁盤FAT

我知道你打算打字,「呃,你不應該這樣做!」然後將我鏈接到一些關於我試圖做的事情是錯誤/不可能/打破一切的規範。不過,我確信有一些方法可以解決這個問題。 :)

我不需要在Windows中的FAT32分區,除了讀取寫在那裏的文件,然後我完成了 - 所以無論解決方案是什麼,這是可以接受的完全無法訪問的磁盤一段的時間。遺憾的是,我無法將整個物理磁盤都置於脫機狀態,因爲它只是安裝了Windows的同一物理設備的一個分區 - 只是分區。

這是到目前爲止我試過的東西...

  1. 谷歌它。我至少得到了一個「這永遠不會發生」的答案。不能的! :)
  2. 冬眠之前卸載磁盤。冬眠後出山。這似乎沒有效果。 Windows仍然認爲FAT與以前相同,所以無論我寫入磁盤的數據是否丟失,我調整的任何文件都已損壞。如果任何文件被緩存,則更糟糕。
  3. 使用DeviceIoControl調用IOCTL_DISK_UPDATE_PROPERTIES來嘗試刷新磁盤(但分區表沒有改變,所以這並沒有真正做任何事情)。

有什麼辦法來使磁盤/卷讀緩存無效,強制窗口回到磁盤?

我想過直接使用libfat打開分區和讀/寫,並繞過緩存或什麼東西是矯枉過正。

回答

0

我的記憶是在OS引導和安裝卷期間讀取FAT表。你不能做關機,然後修改FAT,然後重新啓動Windows?

2

嗯,你不應該這樣做! ;-)

由於操作系統(在這種情況下,Windows是相同的)在休眠映像中寫入其內部文件系統結構的一些內容,如果磁盤內容在「運行「(將休眠看作操作系統執行過程中的一個長時間停頓)。

我可以建議的是,你完全繞過這個問題:格式化分區爲ext2。有些Windows程序可以讀取ext2分區,您可以使用它來獲取數據,大多數現代操作系統應該能夠讀/寫它(因爲它是一種非常常見的Unix風格的文件系統)。避免使用ext2 IFS驅動程序;您希望將文件系統訪問從內核中提取出來並放入可以隨意打開和關閉的程序中。

1

使用Linux將分區創建爲隱藏的FAT32分區。 Linux會讓你掛載分區並寫入文件。 Windows不會讓你掛載分區和讀取文件,而Windows也不會破壞分區。但是有些第三方庫會在Windows運行時讀取分區。

爲了澄清,隱藏意味着分區類型不同於普通的FAT32分區類型。如果您的普通分區類型是0x0C,那麼相應的隱藏類型是0x1C。

0

據我所知,Windows在磁盤級別進行緩存。但是,如果某個分區具有Windows拒絕讀取或寫入的類型(ext2,隱藏的FAT32等),那麼該分區的內容應該永遠不會進入Windows緩存。

+0

對不起,在鍵入它屬於的地方之前,將上述內容意外地輸入爲「答案」。請忽略這個「答案」。 – 2008-10-28 00:00:38

5

所以我終於得到了解決我的問題。在我看來,我將Mount Point和Mount聯繫起來。這些不是一回事。卸下所有卷裝入點不會使卷卸載。它仍然被掛載,但並不意味着你有一個可以在資源管理器中訪問的路徑。

This is the article開始這一切。 這也表明尋找您的EXACT問題,而不是感知問題可以幫助很多!

因此,有兩種解決方案,一種是在緊密循環中不斷調用NtSetSystemInformation(),以便在系統進入休眠狀態時將「SYSTEMCACHEINFORMATION」屬性設置爲基本上清空/清除緩存。然後當你出來時停止循環。這對我來說似乎可能會影響系統性能。所以我放棄了它。

更妙的是,雖然是推薦的解決方案,以MSDN文章中提出了一個稍微不同的問題,它提供方向一個更好的解決問題的辦法:Dismounting Volumes in a Hibernate Once/Resume Many Configuration

現在我有這將刷新寫服務緩存,然後在系統進入休眠/睡眠狀態時鎖定和卸下該卷,並在卷出來時立即釋放捲上的鎖定。

這是一些代碼。 OnHibernate>

volumeHandle = CreateFile(volumePath, 
          GENERIC_READ|GENERIC_WRITE, 
          FILE_SHARE_READ|FILE_SHARE_WRITE, 
          NULL, 
          OPEN_EXISTING, 
          FILE_ATTRIBUTE_NORMAL, 
          0); 
FlushFileBuffers(volumeHandle); 
DeviceIoControl(volumeHandle, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &cbReturned, NULL) ; 
DeviceIoControl(volumeHandle, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &cbReturned, NULL); 
//Keep the handle open here. 
//System hibernates. 

的onResume>

DeviceIoControl(volumeHandle, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &cbReturned, NULL) 
CloseHandle(volumeHandle) 

希望這可以幫助別人的未來:)

+0

現在,如果我能把這個標記作爲未來觀衆接受的答案......好吧。 – Nick 2008-10-31 20:02:22

1

在一個相關但不同的問題在其它的時候,我使用了以下內容:

以管理員身份運行cmd(從批處理文件中運行)

DISKPART
  SELECT G
  REMOVE
  ASSIGN LETTER=G
EXIT

這卸載音量(G :),然後重新安裝它。任何讀取磁盤(在我的情況下假裝爲一個USB大容量存儲設備格式化爲FAT16)將實際上讀取設備,所以讀取緩存有效地刷新。

缺點是啓動DISKPART需要4秒左右的時間,但這在冬眠的情況下可能不是問題。

0

有了DOS,它打字CTRL +Ç,如果兩次我記得好。

對於Linux,sync; echo 3 > /proc/sys/vm/drop_caches或腳本上,當然;-)

隨着Windows的,插值;-)或安裝VirtualBox和Ubuntu的+紅酒協調發展。

嗯,我隱約記得前Windows使用diskcache程序來啓動一個進程,並且diskcache可以用來發送進程信號來刷新和清除整個緩存。如果事情進展緩慢,您可能可以將這樣的信號發送到Windows進程。對不起,我不再使用Windows,部分原因是因爲這種默默無聞。