每个命名了的设备驱动都可以直接从上层来访问,最简单的就是创建一个符号链接,正如上章所讲。
上层应用调用驱动提供的服务可以通过系统函数CreateFile,DeviceIoControl来实现。这两个函数的使用可以从网上找到。
我们看例子ioctrl里面,它实现了三种类型的调用,最常用的是METHOD_BUFFERED,InputBuffer里面可以传入需要处理的参数,OutputBuffer则返回处理的结果或者获取的数据。控制码可由用户自己定义,它就像用户定义的消息码一样,一般用户的定义从0x800到0xFFF。
//
// Device type -- in the "User Defined" range."
//
#define SIOCTL_TYPE 40000 //
// The IOCTL function codes from 0x800 to 0xFFF are for customer use.
//
#define IOCTL_SIOCTL_METHOD_IN_DIRECT \ CTL_CODE( SIOCTL_TYPE, 0x900, METHOD_IN_DIRECT, FILE_ANY_ACCESS )
|
CTL_CODE宏帮助我们生成这个控制码。
上层用户程序首先通过CreateFile调用获得了设备驱动的handle,然后发送一个控制码IOCTL_SIOCTL_METHOD_BUFFERED,操作系统把控制码的消息传给驱动程序,驱动程序在初始化时DriverEntry里面填写了回调函数的指针
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = SioctlDeviceControl;
驱动程序受到系统的IO管理器分发给的这个消息,就会调用SioctlDeviceControl。SioctlDeviceControl里面根据IO请求包里面的IoControlCode来具体处理事务。
//
// Determine which I/O control code was specified.
//
switch ( irpSp->Parameters.DeviceIoControl.IoControlCode ) { case IOCTL_SIOCTL_METHOD_BUFFERED: //ok, this control code, I get it
break; }
|
驱动程序负责处理系统IO管理器分发的IO请求包(IRP)。两个很重要的数据结构是IRP和IO_STACK_LOCATION。IRP是IO request Package的定义,IO_STACK_LOCATION是跟它相关联的堆栈位置,里面存放上层传过来的参数和需要返回的数据。
两个数据结构的定义参考DDK help文档。具体的讲解可以参考Programming the Microsoft Windows Driver Model第五章, Walter Oney, 北大出版社 影印版。
阅读(3949) | 评论(0) | 转发(0) |