雑多2 のバックアップの現在との差分(No.13)


  • 追加された行はこの色です。
  • 削除された行はこの色です。
*WMIでディスク関連の情報を取得.js [#d2c1ad5f]
 function	GetObjectTextList(sQuery){
 	var objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}");
 	var colItems = objWMIService.ExecQuery(sQuery);
 	var s1 = "";
 	
 	for(var emu = new Enumerator(colItems); !emu.atEnd(); emu.moveNext())
 		s1 += emu.item().GetObjectText_();
 	return s1;
 }
 
 var sText = "//Ctrl + C でクリップボードにコピー\n\n\n\n";
 
 sText += GetObjectTextList("SELECT * FROM Win32_DiskDrive\n\n\n\n");
 sText += GetObjectTextList("SELECT * FROM Win32_LogicalDisk\n\n\n\n");
 sText += GetObjectTextList("SELECT * FROM Win32_DiskPartition\n\n\n\n");
 sText += GetObjectTextList("SELECT * FROM Win32_DiskDrivePhysicalMedia\n\n\n\n");
 sText += GetObjectTextList("SELECT * FROM Win32_DiskDriveToDiskPartition\n\n\n\n");
 sText += GetObjectTextList("SELECT * FROM Win32_LogicalDiskRootDirectory\n\n\n\n");
 sText += GetObjectTextList("SELECT * FROM Win32_LogicalDiskToPartition\n\n\n\n");
 sText += GetObjectTextList("SELECT * FROM Win32_IDEController\n\n\n\n");
 sText += GetObjectTextList("SELECT * FROM Win32_IDEControllerDevice\n\n\n\n");
 sText += GetObjectTextList("SELECT * FROM Win32_SystemPartitions\n\n\n\n");
 sText += GetObjectTextList("SELECT * FROM Win32_Volume\n\n\n\n");
 sText += GetObjectTextList("SELECT * FROM Win32_PhysicalMedia\n\n\n\n");
 
 WScript.Echo(sText);
#br


*WMIでパーティションの開始アドレスを取得.js [#k4a04fbb]
 function	GetObjectTextList(sQuery){
 	var objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}");
 	var colItems = objWMIService.ExecQuery(sQuery);
 	var s1 = "";
 	
 	for(var emu = new Enumerator(colItems); !emu.atEnd(); emu.moveNext())
 		s1 += emu.item().GetObjectText_();
 	return s1;
 }
 
 var sText = "//Ctrl + C でクリップボードにコピー\n\n\n\n";
 
 sText += GetObjectTextList("SELECT * FROM Win32_DiskPartition\n\n\n\n");
 sText += GetObjectTextList("SELECT * FROM Win32_LogicalDiskToPartition\n\n\n\n");
 
 WScript.Echo(sText);
#br


*fsutilでサポートされるコマンド(Windows 10) [#yf999a1c]
 ---- サポートされる 8DOT3NAME コマンド ----
 query   システム上の短い名前の動作について現在の設定を照会
 scan    影響を受けるレジストリ エントリを検出
 set     システム上の短い名前の動作を制御する設定を変更
 strip   ディレクトリ内のすべてのファイルの短い名前を削除
 
 ---- サポートされている BEHAVIOR コマンド ----
 query           ファイル システムの behavior パラメーターを照会
 set             ファイル システムの behavior パラメーターを変更
 
 ---- サポートされる DIRTY コマンド ----
 query           dirty ビットの照会
 set             dirty ビットの設定
 
 ---- サポートされる FILE コマンド ----
 createnew               指定されたサイズの新しいファイルの作成
 findbysid               セキュリティ識別子でファイルを検索
 optimizemetadata        ファイルのメタデータの最適化
 queryallocranges        ファイルに割り当てられた範囲の照会
 queryextents            ファイルのエクステントの照会
 queryfileid             指定されたファイルをファイル ID で照会
 queryfilenamebyid       ファイル ID のランダム リンク名を表示
 queryoptimizemetadata   ファイルの最適化メタデータ状態を照会
 queryvaliddata          ファイルの有効なデータ長の照会
 setshortname            ファイルの短い名前の設定
 setvaliddata            ファイルの有効なデータ長の設定
 setzerodata             ファイルのゼロ データの設定
 
 ---- サポートされる FSINFO コマンド ----
 drives          ドライブをすべて一覧表示
 driveType       ドライブの種類の照会
 ntfsInfo        NTFS 固有のボリューム情報の照会
 refsInfo        REFS 固有のボリューム情報の照会
 sectorInfo      セクター情報の照会
 statistics      ファイル システム統計情報の照会
 volumeInfo      ボリューム情報の照会
 
 ---- サポートされる HARDLINK コマンド ----
 create          ハードリンクの作成
 list            ファイルのハードリンクを列挙
 
 ---- サポートされる OBJECTID コマンド ----
 create          オブジェクト ID の作成
 delete          オブジェクト ID の削除
 query           オブジェクト ID の照会
 set             オブジェクト ID の変更
 
 ---- サポートされる QUOTA コマンド ----
 disable         クォータの追跡と強制の無効化
 enforce         クォータの強制の有効化
 modify          ユーザーのディスク クォータの設定
 query           ディスク クォータの照会
 track           クォータの追跡の有効化
 violations      クォータ違反の表示
 
 ---- サポートされる REPAIR コマンド ----
 enumerate      ボリュームの破損ログのエントリの列挙
 initiate       ファイルの修復の開始
 query          ボリュームの自己復旧の状態の照会
 set            ボリュームの自己復旧の状態の設定
 state          ボリュームの破損状態の照会
 wait           修復が完了するまで待機
 
 ---- サポートされる REPARSEPOINT コマンド ----
 delete          再解析ポイントの削除
 query           再解析ポイントの照会
 
 ---- サポートされる RESOURCE コマンド ----
 create          別のトランザクション リソース マネージャーを作成
 info            トランザクション リソース マネージャーに関する情報の表示
 setautoreset    既定のトランザクション リソース マネージャーで次のマウント時にトランザクションの...
 setavailable    整合性よりも可用性を優先するようにトランザクション リソース マネージャーを設定
 setconsistent   可用性よりも整合性を優先するようにトランザクション リソース マネージャーを設定
 setlog          実行しているトランザクション リソース マネージャーの特性を変更
 start           トランザクション リソース マネージャーを開始
 stop            トランザクション リソース マネージャーを停止
 
 ---- サポートされる SPARSE コマンド ----
 queryflag       スパースの照会
 queryrange      範囲の照会
 setflag         スパースに設定
 setrange        スパース範囲の設定
 
 ---- サポートされる TIERING コマンド ----
 queryflags      ボリュームのティアリング動作フラグの表示
 setflags        ボリュームのティアリング動作フラグの有効化
 clearflags      ボリュームのティアリング動作フラグの無効化
 tierlist        ボリュームに関連付けられている記憶域階層の一覧表示
 regionlist      ボリュームの領域と対応する記憶域階層の一覧表示
 
 ---- サポートされる TRANSACTION コマンド ----
 commit          指定されたトランザクションのコミット
 fileinfo        特定のファイルのトランザクション情報の表示
 list            現在実行しているトランザクションの表示
 query           指定したトランザクションに関する情報の表示
 rollback        指定したトランザクションのロールバック
 
 ---- サポートされる USN コマンド ----
 createjournal           USN ジャーナルの作成
 deletejournal           USN ジャーナルの削除
 enumdata                USN データの列挙
 readjournal             USN ジャーナル内の USN レコードの読み取り
 queryjournal            ボリュームの USN データの照会
 readdata                ファイルの USN データの読み取り
 enablerangetracking     ボリュームの書き込み範囲の追跡の有効化
 
 ---- サポートされる VOLUME コマンド ----
 diskfree            ボリュームの空き領域の照会
 dismount            ボリュームのマウントの解除
 querycluster        特定のクラスターを使用するファイルの照会
 filelayout          ファイルについて利用できるすべての情報の照会
 allocationreport    割り当てられたクラスターのレポート
 
 ---- サポートされる WIM コマンド ----
 enumfiles           WIM でバッキングされているファイルの列挙
 enumwims            バッキング WIM ファイルの列挙
 removewim           バッキング ファイルから WIM を削除
 queryfile           特定のファイルのオリジナルを照会
#br


*fsutilのコマンドとWinAPIの対応表 [#p3d44193]
|fsutil file createnew|CreateFile() + SetFilePointer() + SetEndOfFile()|
|fsutil file queryallocranges|DeviceIoControl(FSCTL_QUERY_ALLOCATED_RANGES)|
|fsutil file queryextents|DeviceIoControl(FSCTL_GET_RETRIEVAL_POINTERS)|
|fsutil file queryvaliddata|DeviceIoControl(FSCTL_QUERY_FILE_REGIONS) &size(10){[[1>https://msdn.microsoft.com/en-us/library/jj878209.aspx]][[2>https://www.google.co.jp/search?q=FILE_REGION_USAGE_VALID_NONCACHED_DATA]] GetFileValidData()という名の関数は無い};|
|fsutil file setvaliddata|SetFileValidData()|
|fsutil file setzerodata|DeviceIoControl(FSCTL_SET_ZERO_DATA)|
|fsutil hardlink create|CreateHardLink()|
|fsutil fsinfo statistics|DeviceIoControl(FSCTL_FILESYSTEM_GET_STATISTICS(_EX))|
|fsutil volume querycluster|DeviceIoControl(FSCTL_LOOKUP_STREAM_FROM_CLUSTER)|
|fsutil volume filelayout|DeviceIoControl(FSCTL_QUERY_FILE_LAYOUT)|
#br


*ファイル新規作成時の断片化を軽減する方法 [#w438a9e9]
ファイルサイズがゼロの状態から
a. WriteFile() でファイル全体を一気に書き込む
b. SetFilePointer() と SetEndOfFile() でファイルサイズを拡張しておく(NTFSの場合予約だけで書き込みは発生しない)
のどちらかを実行すると、出来るだけ連続した領域がファイルシステム上で探されて確保されるので断片化しづらい。

ファイル関連の操作は[[Sysinternals Process Monitor>https://technet.microsoft.com/en-us/sysinternals/processmonitor]]で確認できる。 [[1>https://sourceforge.net/p/sevenzip/discussion/45797/thread/967f51bb/?limit=25&page=2#29fd]][[2>https://sourceforge.net/p/sevenzip/feature-requests/981/]]
#br
*Windows標準コマンドで各種ハッシュ計算 / Base64エンコードデコード / bin <-> hex変換する方法(Vista以降) [#ye8f08c8]
[[Windowsのcertutilコマンドでメッセージダイジェストを表示する方法>http://d.hatena.ne.jp/EijiYoshida/20150526/1432625482]]
[[Windowsでbase64エンコード・デコードする方法>http://d.hatena.ne.jp/EijiYoshida/20140618/1403092855]]
[[Windowsでファイルを16進数テキストに変換したり、16進数テキストをファイルに変換したりする方法>http://d.hatena.ne.jp/EijiYoshida/20140618/1403092219]] &size(12){[[CryptBinaryToString function>https://msdn.microsoft.com/ja-jp/library/windows/desktop/aa379887.aspx]]};
#br
*Windowsのメモリ上のファイルキャッシュをクリアする方法(Vista以降) [#ue716713]
[[Sysinternals RAMMap>https://technet.microsoft.com/en-us/sysinternals/ff700229.aspx]]の Menu -> Empty -> Empty Standby List を実行すると、ファイルキャッシュを含むスタンバイタイプのデータがクリアされる。 [[1>http://www.atmarkit.co.jp/fwin2k/win2ktips/1358rammap/rammap.html]][[2>http://www.atmarkit.co.jp/fwin2k/win2ktips/1417sync/sync.html]]

ドライブ単位でなら、ドライブレターを一旦削除する事でもファイルキャッシュがクリアされる。
#br
*NTFS論理ドライブのクラスター番号を論理アドレスに変換.js [#idc8f336]
 //cDriveLetter で指定されたドライブレターと TargetCluster で指定されたクラスター番号から論理アドレスに変換 (NTFS 用)
 //BytesPerSector と BytesPerCluster は WinAPI なら GetDiskFreeSpace()で、cmd なら fsutil fsinfo ntfsinfo で取得可能
 
 var cDriveLetter = "C";
 var TargetCluster = 0x100000;
 
 
 function	GetBytesPerSectorFromDriveLetter(cDriveLetter){
 	var objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}");
 	var listWin32LogicalDiskToPartition   = objWMIService.ExecQuery("SELECT * FROM Win32_LogicalDiskToPartition");
 	var listWin32DiskDriveToDiskPartition = objWMIService.ExecQuery("SELECT * FROM Win32_DiskDriveToDiskPartition");
 	var listWin32DiskDrive                = objWMIService.ExecQuery("SELECT * FROM Win32_DiskDrive");
 	
 	for(var i = 0; i < listWin32LogicalDiskToPartition.Count; i++){
 		if(/Win32_LogicalDisk\.DeviceID=\"([A-Za-z]):\"/i.exec(listWin32LogicalDiskToPartition.ItemIndex(i).Dependent) != null){
 			if(RegExp.$1.toUpperCase() == cDriveLetter.toUpperCase()){
 				for(var i2 = 0; i2 < listWin32DiskDriveToDiskPartition.Count; i2++){
 					if(listWin32LogicalDiskToPartition.ItemIndex(i).Antecedent.toUpperCase() == listWin32DiskDriveToDiskPartition.ItemIndex(i2).Dependent.toUpperCase()){
 						if(/Win32_DiskDrive\.DeviceID=\"(.+)\"/i.exec(listWin32DiskDriveToDiskPartition.ItemIndex(i2).Antecedent) != null){
 							var sDeviceID = RegExp.$1.replace(/\\\\/g, "\\");
 							
 							for(var i3 = 0; i3 < listWin32DiskDrive.Count; i3++){
 								if(listWin32DiskDrive.ItemIndex(i3).DeviceID.toUpperCase() == sDeviceID.toUpperCase()){
 									return	parseInt(listWin32DiskDrive.ItemIndex(i3).BytesPerSector);
 								}
 							}
 						}
 					}
 				}
 			}
 		}
 	}
 	
 	return 0;
 }
 
 
 function	GetBytesPerClusterFromDriveLetter(cDriveLetter){
 	var objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}");
 	var listWin32Volume = objWMIService.ExecQuery("SELECT * FROM Win32_Volume WHERE DriveLetter LIKE '" + cDriveLetter + ":'");
 	
 	if(listWin32Volume.Count > 0){
 		return	parseInt(listWin32Volume.ItemIndex(0).BlockSize);
 	}else{
 		return 0;
 	}
 }
 
 
 function	GetPartitionStartAddressFromDriveLetter(cDriveLetter){
 	var objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}");
 	var listWin32LogicalDiskToPartition = objWMIService.ExecQuery("SELECT * FROM Win32_LogicalDiskToPartition");
 	
 	for(var i = 0; i < listWin32LogicalDiskToPartition.Count; i++){
 		if(/Win32_LogicalDisk\.DeviceID=\"([A-Za-z]):\"/i.exec(listWin32LogicalDiskToPartition.ItemIndex(i).Dependent) != null){
 			if(RegExp.$1.toUpperCase() == cDriveLetter.toUpperCase()){
 				return	parseInt(listWin32LogicalDiskToPartition.ItemIndex(i).StartingAddress);
 			}
 		}
 	}
 	
 	return 0;
 }
 
 
 var BytesPerSector = GetBytesPerSectorFromDriveLetter(cDriveLetter);
 var BytesPerCluster = GetBytesPerClusterFromDriveLetter(cDriveLetter);
 var PartitionStartingAddress = GetPartitionStartAddressFromDriveLetter(cDriveLetter);
 var LogicalAddress = PartitionStartingAddress + (TargetCluster * BytesPerCluster);
 var LogicalBlockAddress = LogicalAddress / BytesPerSector;
 
 var s1  = "//Ctrl + C でクリップボードにコピー"                      + "\n";
 	s1 += "cDriveLetter:\t\t"             + cDriveLetter             + "\n";
 	s1 += "BytesPerSector:\t\t"           + BytesPerSector           + "\n";
 	s1 += "BytesPerCluster:\t\t"          + BytesPerCluster          + "\n";
 	s1 += "PartitionStartingAddress:\t"   + PartitionStartingAddress + "\n";
 	s1 += "TargetCluster:\t\t"            + TargetCluster            + "\n";
 	s1 += "LogicalAddress:\t\t"           + LogicalAddress           + "\n";
 	s1 += "LogicalBlockAddress:\t"        + LogicalBlockAddress      + "\n";
 
 WScript.Echo(s1);
#br
*ベンチマークソフトのベンチマーク用ファイルの採取方法 (NTFS用) [#v5ae9a17]
1. ベンチマークを実行し、対象論理ドライブ直下を調べるかリソースモニターを見て、ベンチマーク用ファイルが何処に作成されるか特定しておく
2. ベンチマークを実行中、fsutil hardlink create コマンドでベンチマーク用ファイルに別名を付け、ファイルの実態への参照数を増やす
&size(11){(ベンチマーク実行中にプロセスを強制終了する方法では FILE_FLAG_DELETE_ON_CLOSE が指定されているケースに対応できない)};
3. 削除されずに残った(ハードリンクで作成した)ファイルをバイナリエディタで覗いてデータパターンを調べたり、断片化数を調べたり、どの論理アドレスに作成されたかを確認する
#br


*RAMDiskの問題点 [#j517a94e]
RAMDiskを使うと、ファイルデータがメモリ上にあるにも関わらず、更に OS のファイルキャッシュに乗ってしまいメモリを二重に消費してしまう。
RAMDiskを使うとファイルデータがメモリ上にあるにも関わらず、更に OS のファイルキャッシュに乗ってしまいメモリを二重に消費してしまう。
#br


*1MBの読み込みは128KBの読み込み*8回に分割される? [#y826d12e]
[[1MBの読み込みは128KBの読み込み*8回に分割される>http://marosama.blogspot.jp/2013/04/ssdhddtxbench.html]]という話を Windows 10 (x64) + Transcend 370S の Device Statistics (GP Log 0x04) で検証。
手順と結果は以下の通り。

1. CreateFile(FILE_FLAG_NO_BUFFERING) で 2MB 以上のファイルを開く
2. ReadFile() で 1MB を読み込むコードをステップ実行
3. smartctl で Device Statistics 読み取り
4. ReadFile() で 1MB を読み込むコードをステップ実行
5. smartctl で Device Statistics 読み取り

||Logical Sectors Read|Number of Read Commands|h
|ReadFile() 2回目直前|1659254096|30839022|
|ReadFile() 2回目直後|1659256144|30839030|
|差|2048|8|

Logical Sectors Read の差:2048 * 論理セクターサイズ:512 = 1,048,576bytes //(1MiB)
なので、1MBの読み込みが128KBの読み込み*8回に分割されている事が確認できた。
#br


*ハイブリッドスリープの書き込み量 [#yc36053d]
ハイブリッドスリープの書き込み量を検証。

|>|CENTER:環境|h
|OS|Windows 10 64bit|
|RAM|4GB|
|hiberfil.sys|3GB|
|SSD|Transcend 370S|
#br
|>|>|>|CENTER:メモリ状況と書き込み量|h
||使用中メモリ|スタンバイメモリ|ホスト書き込み量|
|スリープ|1083 MB|781 MB|0 MB|
|ハイブリッドスリープ|1146 MB|843 MB|320 MB|
|ハイブリッドスリープ &Size(12){(メモリ上に 1 Fill データ約1GB を作成)};|2050 MB|1247 MB|352 MB|
|ハイブリッドスリープ &Size(12){(メモリ上にランダムデータ約1GB を作成)};|2150 MB|1142 MB|1472 MB|

結果は
・物理メモリサイズ分の書き込みが発生する訳ではない
・"使用中" タイプのメモリデータが保存される
・ファイルキャッシュ等の "スタンバイ" タイプのメモリデータは保存されない
・メモリデータは圧縮して保存されるので、圧縮しやすいデータか否かで書き込み量が大幅に変わる
#br
*MFTのアクセス単位 [#k459cfff]
NTFS MFTのファイルレコードサイズは通常1KB(Windows 8以降は FORMAT /L で拡張可能)であるものの、読み書きは4KB単位で行われる。
読み書き量は fsutil fsinfo statistics で確認できる。

 Microsoft Windows [Version 10.0.10586]
 (c) 2015 Microsoft Corporation. All rights reserved.
 
 C:\>fsutil fsinfo statistics C:
 ファイル システムの種類 :     NTFS
 
 UserFileReads :        135997
 UserFileReadBytes :    3619900928
 UserDiskReads :        132814
 UserFileWrites :       31465
 UserFileWriteBytes :   2636247040
 UserDiskWrites :       31365
 MetaDataReads :        56000
 MetaDataReadBytes :    237375488
 MetaDataDiskReads :    87257
 MetaDataWrites :       32346
 MetaDataWriteBytes :   163782656
 MetaDataDiskWrites :   38467
 
 MftReads :                      52559
 MftReadBytes :                  215281664
 MftWrites :                     20305
 MftWriteBytes :                 97267712
 Mft2Writes :                    0
 Mft2WriteBytes :                0
 RootIndexReads :                0
 RootIndexReadBytes :            0
 RootIndexWrites :               0
 RootIndexWriteBytes :           0
 BitmapReads :                   6
 BitmapReadBytes :               6262784
 BitmapWrites :                  8152
 BitmapWriteBytes :              40652800
 MftBitmapReads :                1
 MftBitmapReadBytes :            65536
 MftBitmapWrites :               1471
 MftBitmapWriteBytes :           6033408
 UserIndexReads :                34336
 UserIndexReadBytes :            142667776
 UserIndexWrites :               5937
 UserIndexWriteBytes :           29556736
 LogFileReads :                  8
 LogFileReadBytes :              32768
 LogFileWrites :                 20794
 LogFileWriteBytes :             330182656
 LogFileFull :                   0
 DiskResourceFailure :           0
 VolumeTrimCount :               1744
 AvgVolumeTrimTime (ミリ秒) :    0
 AvgVolumeTrimSize (KB) :        2654
 AvgVolumeTrimSpeed (KB/秒) :    4097371
 VolumeTrimSkippedCount :        0
 VolumeTrimSkippedSize (KB) :    0
 FileLevelTrimCount :            3
 AvgFileLevelTrimTime (ミリ秒) : 168
 AvgFileLevelTrimSize (KB) :     1885956
 AvgFileLevelTrimSpeed (KB/秒) : 11205942
#br
*_ [#o1d84d73]
//*SSDのページサイズはI/Oサイズとアライメント設定で特定できる?

//*読み込み量
//[[FastHash>http://www.vector.co.jp/soft/win95/util/se263655.html]]
//メニュー -> オプション(O) -> ディスクに直接アクセスする(N)
//#br

//*指定サイズのデータを書き込んで SMART 書き込み量を増やす方法
//SMART の読み書き量単位と SSD BlockSize の特定に。
//E:\diskspd -c400M -b123 -d1 -W0 -o1 -t1 -S R:\test.bin
//標準ユーザー権限で実行しないと書き込みが発生しない
//FILE_FLAG_NO_BUFFERING を有効にしてファイルキャッシュを経由せずにデータを書き込める
//ファイルキャッシュに乗らないから空きメモリが減らない
//-b123 でセクターサイズと合わない値をしていしてベンチマークにはしっぱいさせてファイル作成だけで終わらせる
//書き込み内容は 0x00-0xFF の単純な繰り返し
//SMART に合計消去回数があれば、ファイル削除の前後で値を観察。
//すぐに Trim が通知されるとも、通知されればすぐにブロック消去が実行されるとも限らない。
//#br

//*とりあえず指定ファイル全域を読んで SMART 読み込み量を増やす方法
//certutil -hashfile コマンドでファイルのハッシュを計算する事でファイル全域を読み込む。
//certutil -hashfile ファイル名 MD4
//FILE_FLAG_NO_BUFFERING 無しで読み込む為、一旦読むとファイルキャッシュに乗り、何回繰り返しても SMART 読み込み量が増えない。ファイルキャッシュで空きメモリも減少。
//ハッシュアルゴリズムは MD4 が比較的速い
//vista 以降
//#br

//*SMARTの読み書き量の単位を計算
//#br