2

Windows XP、fat32 システム ボリューム上のファイルの最適化に問題があります。デフラグ ツールを作成しているわけではありませんが、ソリューションの一部では、特定のファイル セットをディスク上に連続的に配置する必要があります。これを確実にするために、FSCTL_MOVE_FILE ioctl を使用して、ファイル エクステントをボリューム上の十分なサイズの単一の空き領域エクステントに移動しています。プロセスは次のようになります。

1) ファイルを作成します。

return m_file.Create(path,
                     GENERIC_READ | GENERIC_WRITE,
                     0, NULL,
                     CREATE_ALWAYS,
                     FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH |
                     FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN,
                     NULL);

2) ファイルをゼロで埋めます。

3) ファイルが断片化されていることを確認します。断片化されている場合は、FSCTL_GET_VOLUME_BITMAP を使用してボリューム ビットマップを取得し、十分なサイズの空きクラスター チェーンを見つけます。

4) FSCTL_MOVE_FILE を使用して、ファイルを見つかったエクステントに最適化します。

MOVE_FILE_DATA input;
input.FileHandle = fileHandle;
input.StartingVcn.QuadPart = 0;
input.StartingLcn.QuadPart = freeExtent.lcn;
input.ClusterCount = totalFileClusters;

DWORD bytesReturned = 0; // unused

::DeviceIoControl(
        volumeHandle,
        FSCTL_MOVE_FILE,
        &input,
        sizeof(input),
        NULL,
        0,
        &bytesReturned,
        NULL);

この最後の呼び出しは、NTFS システムと通常のボリュームで正常に機能します。XP の非システム ボリュームも問題ありません。ただし、XP の FAT32 システム ボリュームでは、ほぼ常に INVALID_ARGUMENT (87) エラーが発生します。ファイルはかなり大きく、約 700MB です。ボリュームには約 10GB の空き容量があります。fsctl が失敗した後、エラーが発生する前にファイルの一部が実際に移動されたことがわかります。何度か挑戦しましたが、今のところ50回すべて失敗しています。この方法で大きなファイルを移動すると、以前に解放されていたクラスターがボリューム上の別の何かによって占有されるために失敗する可能性があることを認識しています。しかし、カーネルが存在しない場合、これを軽減する方法がわかりません。私が間違っていること、および/またはどうすれば改善できますか?

4

2 に答える 2

0

2 つの問題。まず、ライブ システムでは、常に他のアクティビティと競合しています (前の回答者が示唆したように)。たとえば、ボリューム ビットマップを取得すると、表示されない他のプロセスでの操作により、既に古くなっている可能性があります。

次に、FAT32 では、一度に移動できる量におそらく制限があります。おそらく、ファイルを 256Kb 単位で移動することを検討する必要があります (別名、キャッシュ マネージャー マッピング ビュー サイズ)。以前は空いていたスペースにヒットするなどのエラーが発生した場合、理由を説明する作業ははるかに少なくなります。

最後に、700Mb のファイルが 700 個の 1Mb チャンクに存在する場合、1 つの 700Mb チャンクよりもパフォーマンスが大幅に向上するとは思えません。

于 2012-12-13T06:31:22.077 に答える