デバイスドライバをはじめ、デバイスにかかわるお困りごとの際はお気軽にお問い合わせください。
【 デバドラ講座22 : デバイスオブジェクト 】
ドライバはAddDeviceで最初に各デバイスを表すデバイスオブジェクトを1つ以上生成します。デバイスオブジェクトには以下の3つがあります。
- 1. PDO (Physical Device Object)
- バス上に接続されているデバイスを示すオブジェクトです。バスドライバまたはPnPマネージャがバス上で検出されたすべてのバスについてPDOを作成します。
- 2. FDO (Functional Device Object)
- デバイスドライバが制御するデバイスを示すオブジェクトです。I/Oマネージャはこのオブジェクトによりデバイスを認識します。IoCreateDevice関数によって作られたオブジェクトです。
- 3. Filter DO (Filter Device object)
- フィルタドライバが制御するデバイスを示すオブジェクトです。フィルタドライバはFDOの上位にも下位にもアタッチすることができます。
AddDeviceルーチンでは、生成したFDOがPDOにアタッチする必要があります。AddDevice関数のプロトコルは次のようになっています。
NTSTATUS Bus_AddDevice(
IN PDRIVER_OBJECT DriverObject, //ドライバオブジェクトのポインタ
IN PDEVICE_OBJECT PhysicalDeviceObject); //下位物理デバイスオブジェクトのポインタ
ここのドライバオブジェクトはDriverEntryに渡されたドライバオブジェクトと同じです。下位物理デバイスオブジェクト(PDO)はPnPマネージャにより生成されたオブジェクトです。このオブジェクトは1階層だけのドライバにも存在します。AddDeviceルーチン内のIoCreateDevice関数によりFDOが作られます。生成されたFDOとPDOはアタッチする必要があります。次にFDOがPDOにアタッチする関数のプロトコルを示します。
PDEVICE_OBJECT IoAttachDeviceToDeviceStack(
IN PDEVICE_OBJECT SourceDevice, //FDOのポインタ
IN PDEVICE_OBJECT TargetDevice); //PDOのポインタ
この関数はアタッチした実際の下位デバイスのポインタを返します。ドライバの中でこのオブジェクトを使うので、このオブジェクトを保存する必要があります。PDOとFDOの関係を図1に示します。
デバイスオブジェクトはドライバオブジェクトと同じように、システム内で構造体として管理されています。ドライバオブジェクトは、ドキュメントに記載されているフィールドにのみアクセスすることができます。次にデバイスオブジェクトの構造体の一部を示します。
typedef struct _DEVICE_OBJECT {
PDRIVER_OBJECT DriverObject;
PDEVICE_OBJECT NextDevice;
PIRP CurrentIrp;
ULONG Flags;
ULONG Characteristics;
PVOID DeviceExtension;
DEVICE_TYPE DeviceType;
CCHAR StackSize;
ULONG AlignmentRequirement;
//ドキュメントに明記されていないフィールドが続きます
} DEVICE_OBJECT;
デバイスオブジェクトを作成する際、デバイスエクステンションのサイズを決める必要があります。デバイスエクステンションはドライバ開発者が独自に設けることができるデバイスに関する情報の構造体です。例えば、PortIOドライバでは次のようなデバイスエクステンションが定義されています。
typedef struct _LOCAL_DEVICE_INFO {
PVOID PortBase; // base port address
ULONG PortCount; // Count of I/O addresses used.
ULONG PortMemoryType; //HalTranslateBusAddress Memory Type
PDEVICE_OBJECT DeviceObject; // The Gpd device object.
PDEVICE_OBJECT NextLowerDriver; // The top of the stack
BOOLEAN Started; //Start Flag
BOOLEAN Removed; //Removed Flag
BOOLEAN PortWasMapped; // If TRUE, we have to unmap on unload
BOOLEAN Filler [1]; //bug fix
IO_REMOVE_LOCK RemoveLock;
} LOCAL_DEVICE_INFO, *PLOCAL_DEVICE_INFO;
デバイスエクステンションは開発者自身が状況に応じて設けるので、ドキュメント化されていない場合ソースコードから真意を理解するのは難しくなります。デバイスエクステンションを定義する場合、ドキュメントを書くことがとても大切です。デバイスオブジェクトとデバイスエクステンションは非ページメモリに作成されます。
ドライバがアンロードされる際、PnPディスパッチルーチンのマイナー関数[IRP_MN_REMOVE_DEVICE]によってデバイスオブジェクトは削除されます。
参考資料
- 「NTドライバプログラミング」
- Peter G. Viscarola、W. Anthony Mason著 久保雅俊、三浦秀朗訳 サイエンスパーク株式会社 監修
- 「Windows NTデバイスドライバプログラミング」
- アート・ベーカー著 WinProgDDK ML和訳プロジェクト訳
- 「WDMデバイスドライバプログラミング完全ガイド」上
- Edword N. Dekker, Jpseph M. Newcomer著 株式会社クイック訳
- 「WDMデバイスドライバ」
- Chris Cant著 エクストランス株式会社訳 サイエンスパーク株式会社 監修