If FILE_FLAG_WRITE_THROUGH is used but FILE_FLAG_NO_BUFFERING is not also specified, so that system caching is in effect, then the data is written to the system cache but is flushed to disk without delay.
てきとうな訳: FILE_FLAG_NO_BUFFERINGを指定せずにFILE_FLAG_WRITE_THROUGHを指定すると、システムキャッシュは有効となり、データはWindowsのシステムキャッシュに書き込まれますがディスクには遅延なくフラッシュされます。
とあるように、CreateFileの第6パラメータdwFlagsAndAttributesにFILE_FLAG_WRITE_THROUGHを指定します。
しかし大量のログを保存するようなケースで保存先がSSDだと、FILE_FLAG_WRITE_THROUGHの指定によりSSDの劣化が通常よりも早く進行することが予想されます。ということで保存先がSSDかどうかでこれらのフラグを付加するかどうかを決めるようにすればいい、ということになります。しかしドライブがSSDかどうかについては、(1)DeviceIOControl (en)でPropertyIdにStorageDeviceSeekPenaltyPropertyを指定したIOCTL_STORAGE_QUERY_PROPERTYを発行してDEVICE_SEEK_PENALTY_DESCRIPTOR構造体のIncursSeekPenaltyが0(False)になっている("no seek penalty")、(2)ATA8-ACSでドライブの回転数を取得してNominal Media Rotation Rate(0x01)になっている、のどちらかで調べることができる、ということまではわかったものの、さて実際のコード例はというとなかなか参考になるものがなく、手詰まりになっていました。
ところがその数日後、NyaRuRuさんがほぼそのまんまの
SSD なら動作を変えるアプリケーションを作る - NyaRuRuが地球にいたころ
という記事を書いているのを見つけました。これだけきちんとしたサンプルがあればDelphiに置き換えるのも簡単です。ということでパート1として(1)の"no seek penalty"を取得する方法を試してみます(以下NyaRuRuさんのコードそのままなので詳細な説明は省略します)。
まずはDeviceIOControlで使用する構造体、定数などを定義します。
FILE_READ_DATA、FILE_READ_ATTRIBUTES、FILE_DEVICE_MASS_STORAGE、FILE_ANY_ACCESS、METHOD_BUFFERED、IOCTL_STORAGE_QUERY_PROPERTYはDelphi XE以降では定義済ですので、Delphi 2009およびそれ以前のバージョン用として定義しています。
これらを使用して物理ドライブ名"\\.\PhysicalDrive#"で指定したドライブが"no seek penalty"かどうかを調べる関数です。 Trueが返ってくればそのドライブはseek penaltyがない、つまりSSDと判断できる、ということになります。ただしこの方法はWindows 7およびそれ以降でしか使用できません(そのかわり管理者権限は不要です)。
次にファイル名/パス名から物理ドライブ番号("\\.\PhysicalDrive#"の#)を取得する方法です。まず構造体、定数などの定義です。 さきほどと同様にIOCTL_VOLUME_GET_VOLUME_DISK_EXTENTSはDelphi XE以降で定義済ですのでDelphi 2009およびそれ以前のバージョンでのみ定義が必要です。
指定したファイル名/パス名の存在する物理ドライブ番号を動的配列に格納する関数です。 これで第2パラメータPhysicalDrivesに物理ドライブ番号が格納されます。
これらの関数を組み合わせて指定したファイル/パスがSSD上に書き込まれるかどうかを調べてみます。 ATA8-ACSでドライブの回転数を取得する方法については次のアーティクルで。
元ねたはもちろんNyaRuRuさんのSSD なら動作を変えるアプリケーションを作る - NyaRuRuが地球にいたころ。すばらしいサンプルを書いていただいたNyaRuRuさんに深く感謝いたします。
2012/10/05追記: CreateFileのフラグについて当初FILE_FLAG_NO_BUFFERINGとFILE_FLAG_WRITE_THROUGHの両方を指定するという記述がありましたが、FILE_FLAG_NO_BUFFERINGを指定したファイルへの書き込みにはFile Bufferingにあるように制限があり、通常の使用には向かないと考えられるため、この点を削除しました。
0 件のコメント:
コメントを投稿