So-net無料ブログ作成

[Windows][Driver][64bit]ドライバの64bit化について 前編 [プログラム]

Driverを書いたことない館長が Windowsの64bit Driverを書くために調べて見つけた情報を書いていく。
主に自分向け。

後編はこちら




■参考ページ

・Driver開発に役立つページ。
http://www.i.u-tokyo.ac.jp/edu/training/ss/msprojects/kernel.html
http://www.codeproject.com/KB/system/driverdev.aspx
http://www.codeproject.com/KB/system/driverdev2.aspx
http://www.codeproject.com/KB/system/driverdev3.aspx
http://www.codeproject.com/KB/system/driverdev4asp.aspx
http://www.codeproject.com/KB/system/driverdev5asp.aspx

・Windows 32bit->64bit化で注意すること
http://download.microsoft.com/download/f/0/5/f05a42ce-575b-4c60-82d6-208d3754b2d6/64-Bit_DrvPort.ppt

・上記を日本語で説明してくれてる感じのページ
http://www.microsoft.com/japan/whdc/driver/kernel/64bit_chklist.mspx

・下記ページの"Supporting 32-Bit I/O in Your 64-Bit Driver"に
Sampleなんかもあって重要
http://msdn2.microsoft.com/en-us/library/aa489627.aspx


■何故64bit化?
・User Modeで動く32bit Applicationは、
64bit Windows上でも32bit互換モードで動く(Microsoft曰く)。
しかし、Kernel driverは64bit対応が必要

■64bitになって変わること
・「64bitへの移行は16bit→32bitより簡単」
http://journal.mycom.co.jp/articles/2004/04/27/amd/

ILP32 -> IL32P64になる。

APIデータモデルintlongpointer
Win32ILP32323232
Win64IL32P64323264
UNIXI32LP64326464


参照:http://journal.mycom.co.jp/photo/articles/2004/04/27/amd/images/004l.jpg

ILP32 - Int型Long型Pointer型のすべてが32bitのこと
IL32P64 - Int型Long型が32bitで、Pointer型が64bitのこと。LLP64(LongLong,Pointer)とも言われている。

で64bitの移行がなぜ簡単と書いているかというと、
今まで使っていたchar, short, int, longといった型は、
なにも変更がないのでそのまま使えるから。
64bitの精度でも使えるようINT64,LONG64などが追加されている。

■ポインタのbit数が問題
変数の型のbit長に変更がないのは、前述の通り。
ただ、Pointerが64bitに変更されている。
ここが64bit化における大きな問題。
例えば、アドレス計算をする際に、ポインタをキャストしていると、おかしくなる。
Microsoftのページにある例だが、

ImageBase = (PVOID)((ULONG)ImageBase | 1);

voidポインタ型のImageBaseに1を足すというアドレス計算をする際に、
ULONGでキャストしているのだが、
64bit OSではvoidポインタ型は64bit長、ULONGは32bit長のため、
この式だと右辺の計算をしている間に、
"(ULONG)ImageBase"の上位32bitが失われることになる。

よって、下記のように書き換える必要があるとのこと。
ULONG_PTRも新しく導入された型。

ImageBase = (PVOID)((ULONG_PTR)ImageBase | 1);

また、前述のように32bitアプリ(32bit互換モードで動作)で
64bitのドライバが使用される場合があるので、
Irp->AssociatedIrp.SystemBufferで構造体を受け渡す場合に
ずれが生じることがある。

これもMicrosoftの例にあるが、下記のような場合、

typedef struct _IOCTL_PARAMETERS {
PVOID Addr;
SIZE_T Length;
HANDLE Handle;
} IOCTL_PARAMETERS, *PIOCTL_PARAMETERS;

32bit アプリがデータを受け渡す場合、
PVOID - 32bit, SIZE_T - 32bit, HANDLE -32bit
である。
これを64bit Driverが同じデータ型で受け取るとすると、
PVOID - 64bit, SIZE_T -64bit, HANDLE - 64bit
なので、
明らかにずれてしまう。

よって、
typedef struct _IOCTL_PARAMETERS_32 {
VOID*POINTER_32 Addr;
INT32 Length;
VOID*POINTER_32 Handle;
} IOCTL_PARAMETERS_32, *PIOCTL_PARAMETERS_32;

この構造体を別途作成して受け取る必要がある。

下記はMicrosoftが提案しているThunkingの手法(2種類)。
http://msdn2.microsoft.com/en-us/library/aa489647.aspx
http://msdn2.microsoft.com/en-us/library/aa489647.aspx
ここではInput Dataの取り扱いしか書いていないが、
もちろん、Outputとしてデータを返す場合も同じように32bit用の構造体で
値を返す必要があるだろう。
そして、Outputを返す場合は、上記の例のように64bitに一端戻すより、
32bitの型のまま計算した方が安全な気がする。
32bitのアプリから呼ばれているかどうかは、
IoIs32bitProcessで知ることができる模様。

Thunkingが必要な型は下記参照。
http://msdn2.microsoft.com/en-us/library/aa489641.aspx

今日の所はここまで。。。


nice!(1)  コメント(0)  トラックバック(0) 

nice! 1

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。

×

この広告は1年以上新しい記事の更新がないブログに表示されております。