Freigeben über


64ビットへのいざない

こんにちは、なおきお~です。

皆さんは、職場や自宅では、どのWindows OSを使用されていますでしょうか?

先日、知人から64ビットのWindows OSは、アプリケーションの互換性が心配だし、デバイス ドライバがあるかどうかわからないので、敷居が高いと言われました。

Windows Vistaのリリース直後に64ビットに移行してしまった私としては、既に気にならないのですが、移行するときは、アプリケーションの互換性やデバイス ドライバの有無は、少なからず心配になりましたので、知人の心配も尤だと思います。

デバイス ドライバを開発されている方の立場からすると、過去に開発したデバイス ドライバの互換性が気になると思いますし、最近では、Windows 7のリリースされるのが、気になるのではないかと思います。また、Windows 7だけでなく、Windows Server 2008 R2もリリースされると思います。

特に、Windows Server 2008 R2 は、32ビット版は提供されず、64ビット版のみになり、サーバーの Windows OS は、完全に64ビットになります。

対して、ノートPCもデスクトップPCも、4GB以上のメモリを搭載PCが増えてきて、クライアント側も、ひしひしと64ビット化を感じます。

ユーザ モードのアプリケーションは、WOW64 (Windows 32-bit on Windows 64-bit ) という機能のおかげで、32ビットでも動作します。

しかしながら、デバイス ドライバは、64ビット版のWindows OS では、ユーザ モードやカーネル モードに関わらず、64ビットである必要があります。

64ビット化が近づきながらも、32ビット版のWindows OS も、まだまだ現役という現状は、32ビットと64ビットのデバイス ドライバを開発する必要があると思います。

2つもデバイス ドライバを開発しなければいけないのか!と思われるかもしれませんが、開発自体は、そんなに大変ではありません。

何故ならば、ほぼソース コードレベルで互換が可能であるということです。つまり、x86・x64・ia64 それぞれのBuild Environmentでbuildすれば、ほとんど終了してしまうのです。

しかし、ソース コード レベルで互換が可能ということは、過去に開発した全ての32ビットのデバイス ドライバに対して、ソース コード レベルで互換性を保証しているわけではありません。意識して、コーディングすれば、ソース コード レベルの互換が可能ということです。また、100%のソース コードの互換ではなく、若干 考慮しなければいけないところもあります。

とはいっても、ソース コードの互換が可能なぐらいの差異なので、過去に開発した32ビットのデバイス ドライバも比較的 容易に移行できるのではないかと思います。

まず、よく使用するデータ型は、このようになっており、ポインター型は、全て64ビット長になります。

データ型

ビット数

LONG, INT

32 ビット符号付き

ULONG,UINT,DWORD

32 ビット符号なし

LONG32, INT32

32 ビット符号付き

LONG64, INT64

64 ビット符号付き

ULONG32,UINT32,DWORD32

32 ビット符号なし

ULONG64,UINT64,DWORD64

64 ビット符号なし

データ型で、よくある問題として、-1を0xFFFFFFFFとコーディングしたり、0x80000000以上のアドレスは、カーネル アドレスと判定するなど、32ビット長に依存しているコーディングです。

こういったのは、-1にするなど、ビット長に依存しないようにコーディングするか、ヘッダ ファイルに定数を定義するなどの工夫が必要になります。

また、定数を定義する場合に、_WIN64や_IA64_や_AMD64_ を使用すると、Build Environmentで適切に定義してくれるので便利だと思います。

なお、このようなコーディングは、デバイス ドライバのみならず、ユーザ アプリケーションでも必要な一般的な考慮点で、ユーザ モードのデバイス ドライバは、このような一般的な考慮点のみで、ほぼ64ビットに移行できると思います。

強いて言えば、プリンタ ドライバの場合、32ビットのユーザ アプリケーションから呼び出される場合、SPLWOW64.EXE経由で呼び出されるため、プロセス空間が、ユーザ アプリケーションではない点です。ただ、通常 プリンタ ドライバは、動作するプロセス空間を認識する必要がないので、問題にならないと思いますが、もし、何らかの事情で、プロセスを意識しているコードがあったとしたら、変更が必要かもしれません。

対してまして、カーネル モードのデバイス ドライバの代表的な考慮点は、32ビットのユーザ アプリケーションから、DeviceIoControl()が呼ばれる場合の実装だと思います。

DeviceIoControl()で指定するInputBufferやOutputBufferの構造体は、IOCTLに依存します。IOCTLが、デバイス ドライバが管理していると同様に、InputBufferやOutputBufferの構造体も管理する必要があります。そのため、32ビットのユーザ アプリケーションから、DeviceIoControl()が呼ばれたら、32ビット用の構造体に変更する必要があります。

WDKのサンプル コード(%BASEDIR%\src\ src\storage\class\classpnp\class.c)にわかりやすい例があるので、そのコードを抜粋してみます。

ClassDeviceControl()という関数で、IOCTL_SCSI_PASS_THROUGHとIOCTL_SCSI_PASS_THROUGH_DIRECTというIOCTLのハンドリングをしています。

_WIN64 の場合のみ、32ビットのプロセスから呼ばれたかどうかをIoIs32bitProcess() という関数で確認しています。もし、32ビットのプロセスから呼ばれたのであれば、SCSI_PASS_THROUGH32という構造体でサイズチェックをしています。

---------- 抜粋 ----------

#if defined (_WIN64)

if (IoIs32bitProcess(Irp)) {

if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSI_PASS_THROUGH32)){

Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;

ClassReleaseRemoveLock(DeviceObject, Irp);

ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);

status = STATUS_INVALID_PARAMETER;

goto SetStatusAndReturn;

}

}

else

#endif

{

if (irpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SCSI_PASS_THROUGH)) {

Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;

ClassReleaseRemoveLock(DeviceObject, Irp);

ClassCompleteRequest(DeviceObject, Irp, IO_NO_INCREMENT);

status = STATUS_INVALID_PARAMETER;

goto SetStatusAndReturn;

}

}

---------- 抜粋 ----------

build するだけで、終了すると書きましたが、実際に本格的な64ビット化する場合は、ソース コードをちょっと変更してre-build するだけでなく、テストをしたり、ドライバ署名をしたりと色々と必要になるので、軽い気持ちで、64ビット化することはできないと思いますが、将来的な64ビット化に備えて、過去に開発したデバイス ドライバや現在 開発しているデバイス ドライバを64ビットのBuild Environmentでre-buildしてみたり、ソース コードを調整してみたり、少しずつ準備をされるとよいと思います。

なお、細かなチェックリストは、WHDC のサイトに公開されているので、本格的な移行際には、このチェックリストを活用していただくのがいいと思います。

64 ビット Microsoft Windows ドライバー用のチェックリスト

https://www.microsoft.com/japan/whdc/driver/kernel/64bit_chklist.mspx

ちなみに、64ビットのDumpファイルの調査は、少々厄介かもしれません。なにせ、引数がレジスタ渡しになってしまったので、32ビットのようにお気軽に引数を確認することができません。ETWトレースなど、他のトラブルシューティングの方法を充実させなければいけないかもしれません。

トラブルシューティングについては、いずれ紹介したいと思います。

 

それでは、また~