ドライブのポリシーが「クイック削除」に設定されているにもかかわらず、小容量のFAT(FAT12)でフォーマットされたUSBフラッシュドライブのFATへの書き込みが遅れているのがわかります。(これはSurpriseRemovalOK
フラグが設定されていることを意味すると思います)。USB経由でドライブに送信されたSCSIコマンドをキャプチャしました。ファイルの切り捨て書き込みがすぐに行われ、ファイル全体(2 512バイトセクター長)がその直後に書き込まれますが、FATの前に20〜90秒の遅延があります。ファイルの書き込みを反映するように更新されます。
ドライブのサイズは重要です。私は15MB以下のサイズのFATファイルシステムでテストして問題を確認しました。16MB以上では、書き込みは遅延されません。16MBは、WindowsでドライブをフォーマットするときにFAT12とFAT16を使用するときに目にするブレークポイントです。(後で追加されたメモ:ただし、FAT12 / FAT16ブレークポイントは、ファイルシステムの絶対サイズではなく、クラスターの数に依存します)。
16MB以上では、Windows Prevent/Allow Medium Removal
は書き込み前にSCSI コマンドを送信し、デバイスを削除しないように要求します。USBスティックは実際にはこれらの要求に対して失敗を返します(削除を保証できないため)が、Windowsはとにかく試みます。15MB以下のトレースでは、 Prevent/Allow Medium Removal
コマンドは表示されません。
(Pythonコードを含む小さなFATファイルシステムをサポートするマイクロコントローラーボードを使用しているときにこの問題を発見しました。マイクロコントローラーがファイルシステムへの書き込みを検出すると、書き込みが完了するのを少し待ってから、新しく書き込まれたPythonコードを自動的に再起動して実行します。しかし、マイクロコントローラーは、書き込みの遅延が原因で、破損したコードまたは破損したファイルシステムを検出していました。)
「クイック削除」が設定されているにもかかわらず、FATへの書き込みが非常に長く遅延するのはなぜですか?ドライブで「イジェクト」を実行することで書き込みを強制できますが、これは「クイック削除」の約束を破ります。ドライブを早めに引っ張ると、FATテーブルが不正確になります。これは、「ハードウェアの安全な取り外し」を使用する必要がないという以下のスクリーンショットの説明とは異なります。これはバグですか、それとも何か不足していますか?すべての書き込みを手動の「イジェクト」なしですぐに強制的に実行する方法はありますか?
これは、Wireshark / USBPcapトレースからの剪定抽出で、問題を示しています。既存のファイルを切り捨ててから、その新しいコピーを書き込みます。にコメントを追加しました###
。USBドライブへの書き込みのほとんどは、トレースの約5秒後に行われますが、最後のFAT書き込みは26秒まで行われません。
No. Time Source Destination Protocol Length Info
### write directory entry to truncate file
13 5.225586 host 1.2.2 USBMS 58 SCSI: Write(10) LUN: 0x00 (LBA: 0x00000041, Len: 8)
14 5.225838 host 1.2.2 USB 4123 URB_BULK out
### write FAT entries to truncate file
16 5.230488 host 1.2.2 USBMS 58 SCSI: Write(10) LUN: 0x00 (LBA: 0x0000003b, Len: 1)
17 5.230707 host 1.2.2 USB 539 URB_BULK out
19 5.235110 host 1.2.2 USBMS 58 SCSI: Write(10) LUN: 0x00 (LBA: 0x0000003e, Len: 1)
20 5.235329 host 1.2.2 USB 539 URB_BULK out
### write directory entry for
22 5.252672 host 1.2.2 USBMS 58 SCSI: Write(10) LUN: 0x00 (LBA: 0x00000041, Len: 8)
23 5.252825 host 1.2.2 USB 4123 URB_BULK out
### write out file data (2 sectors of 512 bytes)
25 5.257416 host 1.2.2 USBMS 58 SCSI: Write(10) LUN: 0x00 (LBA: 0x000000c1, Len: 2)
26 5.257572 host 1.2.2 USB 1051 URB_BULK out
### 20 second delay
### finally, write FAT entries to indicate used sectors
79 26.559964 host 1.2.2 USBMS 58 SCSI: Write(10) LUN: 0x00 (LBA: 0x0000003b, Len: 1)
80 26.560191 host 1.2.2 USB 539 URB_BULK out
82 26.560834 host 1.2.2 USBMS 58 SCSI: Write(10) LUN: 0x00 (LBA: 0x0000003e, Len: 1)
83 26.560936 host 1.2.2 USB 539 URB_BULK out
Windows 7とWindows 10の両方で、通常のフラッシュドライブと、小さなUSB MSCドライブをエミュレートするマイクロコントローラーボードを使用して、このようなトレースを生成しました。
明確にするために、これはFAT12でフォーマットされたドライブで、Windowsのフォーマットツールでは単に「FAT」と呼ばれています。
main.py
、ファイルが書き込まれたことを検出すると、自動リセットして実行するように設定されています。書き込みが完了するまで少し遅れますが、数十秒はかかりません。この自動再起動を無効にすることもできますが、書き込みがタイムリーに完了するようにするには、ドライブを「イジェクト」する必要があります。ユーザーに取り出しを要求するのは面倒です。それは避けたいです。