【FatFs】車載外部ストレージ その121【SDカード直接制御④】

【FatFs】車載外部ストレージ その121【SDカード直接制御④】 車載外部ストレージ

バックナンバーはこちら。
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で認識
フクさん
フクさん

そして、全体構成

FatFS、FileSystem、DiskIO、DeviceIoControl、読み書き実施、SDHC、WindowsAPIを駆使してSDを直接制御
太郎くん
太郎くん

前回のソースコードの修正差分で気になった部分は以下だね。

  • 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_LOCK_VOLUME - Win32 apps
Locks a volume if it is not in use.

FSCTL_DISMOUNT_VOLUME

FSCTL_DISMOUNT_VOLUME - Win32 apps
Dismounts a volume regardless of whether or not the volume is currently in use. For more information, see the Remarks se...
フクさん
フクさん

ざっくり説明すると、
FSCTL_LOCK_VOLUMEは
「ボリュームをロックしてOSや他のアプリケーションからのアクセスを禁止する」
FSCTL_DISMOUNT_VOLUMEは、その名の通り、
「ボリュームのアンマウントしてOSや他のアプリケーションから一時的に見えないようにする」
ってところだ。

太郎くん
太郎くん

何となくわかってきたぞ。
そのままだとOSもSDカードことリムーバブルディスクを制御しているから、
その制御を一時的に奪うってところか。

フクさん
フクさん

その通り。
これをやっておかないと読み書き等のアクセスがOSからはじかれるし、
場合によってはブルースクリーン・・・。

太郎くん
太郎くん

(マジか・・・)

まとめ

フクさん
フクさん

まとめだよ。

  • OSから見たマウント解除方法説明。
  • CreateFileに「\\.\d」を指定すると論理ドライブのハンドルを取得できる。
  • DeviceIoControlに以下の制御コードを渡すことでOSの論理ドライブアクセスを禁止できる。
    • FSCTL_LOCK_VOLUME。
    • FSCTL_DISMOUNT_VOLUME。

バックナンバーはこちら。

コメント

タイトルとURLをコピーしました