windowsNT4.0下设备驱动程序的开发与应用
_WRITE]=
XxWriteDispatch
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=XxSelfDispatch
DriverObject->DriverUnload=XxUnload
//生成Windows NT Executive知道的设备名
RtlInitUnicodeString(NtDeviceName, SelfDeviceName);
//生成自己的设备
Status=IoCreateDevice(
DriverObject, // Driver对象
sizeof(SELF_DEVICE_INFO), // Device对象
Extension结构大小
NtDeviceName,
DeviceType,
0,
FALSE, // 不执行
DeviceObject //Device对象指针
);
//生成Win32子系统下的用户程序可识别的设备名
RtlInitUnicodeString(Win32DeviceName, SelfWin32Name);
//联接内部设备名与Win32子系统下的设备名
Status = IoCreateSymbolicLink( Win32DeviceName, NtDeviceName);
//利用RtlQueryRegistryValues函数读出注册表中Parameters下的参数值,初始化自己的硬件
...
}
4 驱动程序服务例程
驱动程序初始化之后,始终等待发自用户的命令或由其它事件源引起的事件。一旦命令或事件发生,I/O管理器就调用相应的服务例程提供服务。而几乎所有的I/O都是通过I/O请求包IRP驱动的。所谓IRP驱动,就是I/O管理器负责在非分页的系统内存中分配一定空间,当接受用户发出的命令或由事件引发后,将工作指令按一定的数据结构置于其中,传递到驱动程序服务例程。换言之,IRP包含了驱动程序服务例程所需要的信息指令。表2、表3为IRP的一些数据结构。
同时,I/O管理器和驱动程序都需要在所有时候知道一个I/O设备所进行的情况。系统提供Device对象以满足此要求。该对象在DriverEntry例程中生成设备时由系统创建后,分配给驱动程序,并在整个驱动程序生存期内有效。当I/O管理器调用驱动程序服务例程时,传递该对象。表4为Device对象的外部可见域。
表2 IRP标头中外部可见的域
表3 IRP堆栈单元的一些内容
表4 Device 对象的外部可见域
其中,DeviceExtension域是一个重要的数据结构。它是由I/O管理器创建并自动挂接到Device对象的非分页池,是保存驱动程序任意全局变量的最好办法。因为DeviceExtension是驱动程序特定的,要自定义它的数据结构。
下面是一个驱动程序服务例程利用Device对象和IRP的片段:
NTSTATUS XxSelfDispatch(IN PDEVICE_OBJECT pDO IN PIRP pIrp);
{
PLOCAL_DEVICE_INFO pLDI;
PIO_STACK_LOCATION pIrpStack;
PULONG pIOBuffer;
//得到全局信息
pLDI = (PSELF_DEVICE_INFO)pDO->DeviceExtension;
pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
//得到由用户应用程序发来的用户数据,并在需要时,将结果通过此变量返回给用户
pIOBuffer=PULONGpIrp->AssociatedIrp.System
Buffer;
// 由IRP携带的信息决定驱动程序的执行
switch (pIrpStack->MajorFunction)
{
case IRP_MJ_CREATE:
case IRP_MJ_CLOSE:
Status = STATUS_SUCCESS;
break;
case IRP_MJ_DEVICE_CONTROL:
//由Parameters进一步解释控制代码含义
switch (pIrpStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_Function1:
//执行功能代码
Field1 = pLDI->SelfField1;
...
break;
case IOCTL_Function2:
//执行功能代码
...
break;
}
break
}
// 返回I/O操作的状态
pIrp->IoStatus.Status = Status;
IoCompleteRequest(pIrp IO_NO_INCREMENT);
return Status;
}
5 驱动程序终止例程
Unload例程负责取消由DriverEntry例程所做的任何事情,包括解除属于该驱动程序的任何硬件资源的分配,以及删除属于驱动程序的任何内核对象。通常这仅在系统关闭时需要。
VOID XxUnload(PDRIVER_OBJECT DriverObject)
{
PLOCAL_DEVICE_INFO pLDI;
UNICODE_STRING Win32DeviceName;
// 得到全局数据,根据全局数据进行清理工作
pLDI=PLOCAL_DEVICE_INFODriverObject->Device
Object->DeviceExtension
if (pLDI->Field2 == TRUE)
{
...
// 删除分配的设备名及设备
RtlInitUnicodeString(Win32DeviceName, SelfWin32 Name);
IoDeleteSymbolicLink(Win32DeviceName);
IoDeleteDevice(pLDI->DeviceObject);
}
6 用户层应用程序与驱动程序间的接口
驱动程序完成后,将在系统重新引导时装入并初始化(由DriverEntry例程完成)。此时,驱动程序处于可用状态,等待用户层应用程序使用。用户层应用程序可以:
·打开该设备文件(由IRP_MJ_CREATE功能代码完成)
·读出数据(由IRP_MJ_READ功能代码完成)
·写入数据(由IRP_MJ_WRITE功能代码完成)
·执行用户自定义的功能代码(由IRP_MJ_DEVICE_CONTROL功能代码完成)
·关
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)