首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

windowsNT4.0下设备驱动程序的开发与应用(2)

windowsNT4.0下设备驱动程序的开发与应用(2)

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=PULONGpIrp->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_INFODriverObject->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功能代码完成)
·关闭该设备文件(由IRP_MJ_CLOSE功能代码完成)
以下是部分实现代码:
void main()
{
HANDLE hndFile; // 由CreateFile得到
union {
ULONG LongData;
USHORT ShortData;
UCHAR CharData;
 }DataBuffer; //从设备驱动程序中得到的数据
LONG IoctlCode; //功能代码
ULONG DataLength;
LONG Parameter1;
//调用IRP中的IRP _MJ_CREATE功能
hndFile = CreateFile(
″\\\\.\\SelfWin32Name″, // 打开设备文件″ SelfWin32Name″
返回列表