windows 2000 中断等级(IRQL)
windows 2000 中断等级(IRQL)
产生对象 IRQL名称 用途
1、 硬件 HIGH_LEVEL 机器校验和总线错误
2、 POWER_LEVEL 电源故障中断
3、 IPI_LEVEL MP系统处理器间门铃
4、 CLOCK2_LEVEL 间隔时钟2
5、 CLOck1_LEVEL 间隔时钟1
6、 PROFILE_LEVEL 配置文件计时器
7、 DORQL IO设备中断的平台依赖行等级数
8、 软件 DISPATCH_LEVEL 线程调度和延迟过程调用的执行
9、 APC_LEVEL 异步过程调用执行
10、 PASSIVE_LEVEL 下常线程执行等级
访问寄存器
知道硬件功能后,还须知道如何通过程序设计方法引用设备的寄存器.为了达到这一目标,还必须知道两种信息.
1.设备的第一个寄存器地址.
2.寄存器所有的地址空间.
通常设备寄存器位于连续的地址空间上.因此,第一个寄存器的地址是访问所有其他寄存器必须的线索.不幸的是,地址这一术语在不同平台上的虚拟地址空间中具有不同的含义.可以通过CPU专用的I/O指令,或者通过标准内在引用指令.
CPU专用I/O指令访问.
Intel x86体系结构中,I/O地址空间是64KB大小(16位),在汇编语言定义两个指令用于在此空间中读取和写入:IN和OUT
访问I/O空间中6各端口的HAL宏
READ_PORT_XXX 从一个端口读取一个单值
WRITE_PORT_XXX 将一个单值写入端口
READ_PORT_BUFFER_XXX 从连续的I/O端口读取一组值
WRITE_PORT_BUFFER_XXX 将一组值写入连续的I/O端口.
内存映射寄存器
READ_REGISTER_XXX 从I/O寄存器读取一个单值
WRITE_REGISTER_XXX 将一个单值写入一个I/O寄存器
READ_REGISTER_BUFFER_XXX 从连续的I/O寄存器读取一组值
WRITE_REGISTER_BUFFER_XXX 将一组值写入连续的I/O寄存器.
驱动程序常用列程
1.DriverEntry(驱动程序入口)
pDriverObject->DriverEntry = DriverEntry;
IRQL = PASSIVE_LEVEL
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING pRegistryPath){}
2.Reinitialize(重新初始化例程)
pDriverObject->DriverReinitialize = DriverReinitialize;
3.DriverUnload(卸载例程)
pDriverObject->DriverEntry = DriverEntry;
4.Shutdown(关闭例程)
pDriverObject->DriverShutdown = DriverShutdown;
5.Bugcheck(故障检验例程)
pDriverObject->DriverBugcheck = DriverBugcheck;
6.CreateDispatch(当用户层调用中CreateFile时执行. IRP_MJ_CREATE)
7.CloseDispatch(当用户层调用CloseHandle时执行. IRP_MJ_CLOSE)
8.WriteDispatch(当用户屋调用WriteFile时执行. IRP_MJ_WRITE)
9.ReadDispatch(当用户层调用ReadFile时执行. IRP_MJ_READ)
10.DeviceControlDispatch(当用户层调用DeviceIoControl执行.IRP_MJ_DEVICE_CONTROL)
Dispatch列程邦定到驱动对象的MajorFunction指针上
pDriverObject->MajorFunction[IRP_MJ_CREATE] =CreateDispatch;
pDriverObject->MajorFunction[IRP_MJ_CLOSE] =CloseDispatch;
pDriverObject->MajorFunction[IRP_MJ_WRITE] =WriteDispatch;
pDriverObject->MajorFunction[IRP_MJ_READ] =ReadDispatch;
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] =DeviceControlDispatch;
11.DriverStartIo(当设备须要开始数据传输时执行)
pDriverObject->DriverStartIo = DriverStartIo;
同步回调例程
1.ControllerControl例程
单一的控制器(卡)支持多个函数.每次卡上只有一个函数运行.当I/O完成时,驱动程序释放控制器.通常在一个DpcForIsr例程中.
2.AdapterControl例程
当所有权得到时允许时,回调例程执行.通常是一个DMA通道.
3.SynchCritSection例程
通常用于访问寄存器同步.
IRP结构
typedef struct _IRP {
CSHORT Type;
USHORT Size;
//
// Define the common fields used to control the IRP.
//
//
// Define a pointer to the Memory Descriptor List (MDL) for this I/O
// request. This field is only used if the I/O is "direct I/O".
//
PMDL MdlAddress; //指向用户空间的内存描述列表
//
// Flags word - used to remember various flags.
//
ULONG Flags; //
//
// The following union is used for one of three purposes:
//
// 1. This IRP is an associated IRP. The field is a pointer to a master
// IRP.
//
// 2. This is the master IRP. The field is the count of the number of
// IRPs which must complete (associated IRPs) before the master can
// complete.
//
// 3. This operation is being buffered and the field is the address of
// the system space buffer.
//
union {
struct _IRP *MasterIrp;
LONG IrpCount;
PVOID SystemBuffer; //指向系统缓冲区
} AssociatedIrp;
//
// Thread list entry - allows queueing the IRP to the thread pending I/O
// request packet list.
//
LIST_ENTRY ThreadListEntry;
//
// I/O status - final status of operation.
//
IO_STATUS_BLOCK IoStatus; // 包含I/O请求的状态
//
// Requestor mode - mode of the original requestor of this operation.
//
KPROCESSOR_MODE RequestorMode;
//
// Pending returned - TRUE if pending was initially returned as the
// status for this packet.
//
BOOLEAN PendingReturned;
//
// Stack state information.
//
CHAR StackCount;
CHAR CurrentLocation;
//
// Cancel - packet has been canceled.
//
BOOLEAN Cancel; //表示IRP已经取消
//
// Cancel Irql - Irql at which the cancel spinlock was acquired.
//
KIRQL CancelIrql;
//
// ApcEnvironment - Used to save the APC environment at the time that the
// packet was initialized.
//
CCHAR ApcEnvironment;
//
// Allocation control flags.
//
UCHAR AllocationFlags;
//
// User parameters.
//
PIO_STATUS_BLOCK UserIosb;
PKEVENT UserEvent;
union {
struct {
PIO_APC_ROUTINE UserApcRoutine;
PVOID UserApcContext;
} AsynchronousParameters;
LARGE_INTEGER AllocationSize;
} Overlay;
//
// CancelRoutine - Used to contain the address of a cancel routine supplied
// by a device driver when the IRP is in a cancelable state.
//
PDRIVER_CANCEL CancelRoutine;
//
// Note that the UserBuffer parameter is outside of the stack so that I/O
// completion can copy data back into the user's address space without
// having to know exactly which service was being invoked. The length
// of the copy is stored in the second half of the I/O status block. If
// the UserBuffer field is NULL, then no copy is performed.
//
PVOID UserBuffer; //I/O缓冲区的用户空间地址
//
// Kernel structures
//
// The following section contains kernel structures which the IRP needs
// in order to place various work information in kernel controller system
// queues. Because the size and alignment cannot be controlled, they are
// placed here at the end so they just hang off and do not affect the
// alignment of other fields in the IRP.
//
union {
struct {
union {
//
// DeviceQueueEntry - The device queue entry field is used to
// queue the IRP to the device driver device queue.
//
KDEVICE_QUEUE_ENTRY DeviceQueueEntry;
struct {
//
// The following are available to the driver to use in
// whatever manner is desired, while the driver owns the
// packet.
//
PVOID DriverContext[4];
} ;
} ;
//
// Thread - pointer to caller's Thread Control Block.
//
PETHREAD Thread;
//
// Auxiliary buffer - pointer to any auxiliary buffer that is
// required to pass information to a driver that is not contained
// in a normal buffer.
//
PCHAR AuxiliaryBuffer;
//
// The following unnamed structure must be exactly identical
// to the unnamed structure used in the minipacket header used
// for completion queue entries.
//
struct {
//
// List entry - used to queue the packet to completion queue, among
// others.
//
LIST_ENTRY ListEntry;
union {
//
// Current stack location - contains a pointer to the current
// IO_STACK_LOCATION structure in the IRP stack. This field
// should never be directly accessed by drivers. They should
// use the standard functions.
//
truct _IO_STACK_LOCATION *CurrentStackLocation; //I/O堆栈位,保存I/O请求的函数代码和参数
s
//
// Minipacket type.
//
ULONG PacketType;
};
};
//
// Original file object - pointer to the original file object
// that was used to open the file. This field is owned by the
// I/O system and should not be used by any other drivers.
//
PFILE_OBJECT OriginalFileObject;
} Overlay;
//
// APC - This APC control block is used for the special kernel APC as
// well as for the caller's APC, if one was specified in the original
// argument list. If so, then the APC is reused for the normal APC for
// whatever mode the caller was in and the "special" routine that is
// invoked before the APC gets control simply deallocates the IRP.
//
KAPC Apc;
//
// CompletionKey - This is the key that is used to distinguish
// individual I/O operations initiated on a single file handle.
//
PVOID CompletionKey;
} Tail;
} IRP, *PIRP;
操作IRP头的函数
IoStatrtPacket 把IRP发送到Start I/O例程 Dispatch
IoCompleteRequest 指示所有处理都已经完成. DpcForcIar
IoStartNextPacket 把下一个IRP发送到Start I/O例程 DpcForIsr
IoCallDriver 把IRP发送到别一个驱动 Dispatch
IoAllocateIrp 请求额外的IRP Dispatch
IoFreeIrp 释放驱动程序分配的IRP I/O Completion
IRP堆栈位置
IoGetCurrentIrpSteckLocation 获取指向调用者堆栈(Stack slot)的指针 Dispatch
IoMarkIrpPending 把调用者堆栈槽标志为需要进一步处理 Dispatch
IoGetNextIrpStackLocation 获取指向下一个低级驱动程序的堆栈槽的指针 Dispatch
IoSetNextIrpStackLocation 把I/O堆栈指针压入一个位置. Dispatch
IoSetCompleteRoutime 把I/O完成例程放在下一个低级驱动程序的I/O堆栈槽上 Dispatch
驱动程序对象可设置的字段.
PDRIVER_STARTIO DriverStartIo 驱动程序 Start I/O 例程的地址
PDRIVER_UNLOAD DriverUnload 驱动程序 Unload例程的地址.
PDRIVER_DISPATCH MajorFunction 驱动程序Dispatch例程表,由I/O操作代码索引
PDEVICE_OBJECT DeviceObject 该驱动程序建立的设备对象的链接列表
设备对象结构
PVOID DeviceExtension 指向设备扩展结构
PDRIVER_OBJECT DriverObject 指向该设备的驱动程序对象
ULONG Flags 规定设备的缓冲策略是(DO_BUFFERED_IO 或者 DO_DIRECT_IO)
PDEVICE_OBJECT NextDevice 指向属于该驱动程序的下一个设备
CCHAR StackSize 发送到该设备的IRP所需的最少数量的I/O堆栈位置
ULONG AlignmentRequirement 缓冲区要求内存调整
操作设备对象的函数
IoCreateDevice 建立设备对象 DirverEntry或AddDevice
IoCreateSymbolicLink 使设备对象对Win32可见 DirverEntry或AddDevice
IoAttachDevice 把一个过滤器附加在设备对象上 DirverEntry或AddDevice
IoAttachDeviceByPointer 把一个过滤器附加在设备对象上 DirverEntry或AddDevice
IoGetDeviceObjectPointer 把驱动程序放在另一个驱动程序之上 DirverEntry或AddDevice
IoCallDriver 把IRP请求发送到另一个驱动程序 Dispatch
IoDetachDevice 断开与低级驱动程序的连接 Unload 或 RemoveDeivce
IoDeleteSymbolicLink 从Win32 名字空间中删除设备对象 Unload 或 RemoveDeivce
IoDeleteDevice 从系统中删除设备对象 Unload 或 RemoveDeivce
控制器对象的访问函数
IoCreateController 建立控制器对象
IoAllocateController 请求控制器的独占权
IoFreeController 释放控制器拥有权
IoDeleteController 从系统中删除控制对象
操纵适配器对象的函数 (主要用于DMA传输)
IoGetDmaAdapter 获取指向适配器对象的指针
AllocateAdapterChannel 请求单独拥有DMA硬件
MapTransfer 建立用于数据传输的DMA硬件
FlushAdapterBuffers 数据部分传输之后,清洗缓冲区数据
FreeMapRegisters 释放映射寄存器
FreeAdapterChannel 释放适配器对象
中断对象
中断对象仅仅给内核中断调度程序提供了一种寻找方法,在一个中断发生时找到正确的服务例程
操作中断对象
HalGetInterruptVector 将总线相关的中断失量转换成系统范围的值.
IoConnectInterrupt 将中断服务例程与一个中断失量关联.
KeSynchronizeExecution 同步运于不同的IRQL等级上的驱动程序
IoDisconnectInterrupt 删除中断对象
内存分配类型
1.通过内核堆栈分配(堆栈大小为12K)
2.使用池区域 使用ExAllocatePool 或 ExFreePool
3.区域缓冲区
先使用 ExAllocatePool 再使用ExInitializeZone 初始化
分配使用ExAllocateFromZone 或者 ExInterLocked-AllocateFromZone(互锁的函数)
释放区域 ExFreeToZone 或 InterLockedFreeToZone(互锁)
使用ExExtendZone 或 ExInterlockedExtendZone 扩展
4.使用后备列表
初始化:ExInitializeNPagedLookasideList 或 ExInitializePagedLookasideList
分配:ExAllocateNPagedLookasideList 或 ExAllocatePagedLookasideList
释放:ExFreeToNPageLookasideList 或 ExFreeToPageLookasideList
删除后备列表:ExDeleteNPageLookasideList 或 ExDeletePageLookasideList
中断同步
中断阻止(interrupt blocking)
KeRaiselrql 将CPU的IRQL级别改为规定的值
KeLowerlrql 将低CPU的IRQL值
KeGetCurrentIrql 返回发出调用的CPU的IRQL值
IO完成例程的IRQL是由下层驱动程序调用而决定的固引入了内核事件来处理IO完成例程