バックナンバーはこちら。
https://www.simulationroom999.com/blog/In-vehicle-external-storage-backnumber/
はじめに
FatFs WinシミュレーションでSDカードに直接制御する話。
今回は「FatFs改造」の話の詳細。
登場人物
博識フクロウのフクさん
イラストACにて公開の「kino_k」さんのイラストを使用しています。
https://www.ac-illust.com/main/profile.php?id=iKciwKA9&area=1
エンジニア歴8年の太郎くん
イラストACにて公開の「しのみ」さんのイラストを使用しています。
https://www.ac-illust.com/main/profile.php?id=uCKphAW2&area=1
実験手順
想定実験手順は以下。
今回は「FatFs改造」の話の詳細。
- FatFs改造方針を考える
- FatFs改造 ← これの2回目/全3回
- FatFsでSDカードのFAT認識
- FatFsでファイル書き込みとWindowsでの認識
- FatFsでFAT32フォーマットしてWindowsで認識
そして、全体構成
前回のソースコードの修正差分で気になった部分は以下だね。
- dismount_volume関数
- main.cのVolToPart配列
まずはdismount_volume関数の中身を説明しよう。
dismount_volume関数
まずはdismount_volume関数だけ抜き出してみる。
void dismount_volume(const TCHAR drvlet[])
{
int i;
DWORD dummy;
for (i = 0; i < 10; i++) {
HANDLE *pSD = &hSD[i];
WCHAR szlogicalDrvName[10] = L"\\\\.\\d:";
if (drvlet[i] == '\0') {
break;
}
szlogicalDrvName[4] = drvlet[i];
if ((*pSD != 0)) {
DeviceIoControl(*pSD, FSCTL_UNLOCK_VOLUME, 0, 0, 0, 0, &dummy, 0);
CloseHandle(*pSD);
*pSD = 0;
}
*pSD = CreateFileW(szlogicalDrvName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
DeviceIoControl(*pSD, FSCTL_LOCK_VOLUME, 0, 0, 0, 0, &dummy, 0);
DeviceIoControl(*pSD, FSCTL_DISMOUNT_VOLUME, 0, 0, 0, 0, &dummy, 0);
}
}
関数の名称からすると、指定したvolumeのマウントを解除するってことなんだろうが・・・。
結局何をしてるの?
リムーバブルディスクのハンドル取得、ロック、アンマウントをやってる。
(さっぱりわからん・・・。)
リムーバブルディスクのハンドル取得
まず、「リムーバブルディスクのハンドル取得」だが、
CreateFileWで実施している。
通常ファイル名を指定するところにリムーバブルディスクの論理ドライブ名を指定する。
例えば、Dドライブであれば、「\\.\d」。
エスケープシーケンスを含めると「\\\\.\\d」になるけどねー。
注意点としては
FILE_SHARE_READ | FILE_SHARE_WRITEのフラグをオプションに追加しておく必要がある。
ほー。
そういう指定で「リムーバブルディスクのハンドル取得」ができちゃうんだ!
まぁOS側も該当リソースを握ってるんで、
そのまま読み書き等のアクセスするとアクセス例外が発生しちゃうんだけどね。
え?
じゃーどうするの?
で、必要になるのがロックとアンマウント
リムーバブルディスクのロックとアンマウント
実際にコード上でやってるのはDeviceIoControlで、引数にFSCTL_LOCK_VOLUMEとFSCTL_DISMOUNT_VOLUMEが入ってるところ。
確かにあるねー。
FSCTL_LOCK_VOLUMEとFSCTL_DISMOUNT_VOLUMEの詳細情報については以下参照。
FSCTL_LOCK_VOLUME
FSCTL_DISMOUNT_VOLUME
ざっくり説明すると、
FSCTL_LOCK_VOLUMEは
「ボリュームをロックしてOSや他のアプリケーションからのアクセスを禁止する」
FSCTL_DISMOUNT_VOLUMEは、その名の通り、
「ボリュームのアンマウントしてOSや他のアプリケーションから一時的に見えないようにする」
ってところだ。
何となくわかってきたぞ。
そのままだとOSもSDカードことリムーバブルディスクを制御しているから、
その制御を一時的に奪うってところか。
その通り。
これをやっておかないと読み書き等のアクセスがOSからはじかれるし、
場合によってはブルースクリーン・・・。
(マジか・・・)
まとめ
まとめだよ。
- OSから見たマウント解除方法説明。
- CreateFileに「\\.\d」を指定すると論理ドライブのハンドルを取得できる。
- DeviceIoControlに以下の制御コードを渡すことでOSの論理ドライブアクセスを禁止できる。
- FSCTL_LOCK_VOLUME。
- FSCTL_DISMOUNT_VOLUME。
バックナンバーはこちら。
コメント