什么是IRP:
I/O request packets,简称IRP。即输入输出请求包。它是WINDOWS内核中的一种非常重要的数据结构。上层应用程序与底层驱动程序通信时,应用程序会发出I/O请求。操作系统将相应的I/O请求转换为相应的IRP。不同的IRP会根据类型被分派的不同的派遣历程中进行处理。
作用:
上层应用程序于底层驱动之间的通讯,即EXE程序和SYS之间的通讯。
应用程序 想要访问内核数据,必须通过IRP数据。又叫IRP请求,当应用程序和驱动交互时,发送一个IRP请求,IRP会在各层设备驱动个之间来回传动和转发。
五种常用的IRP类型:
#define IRP_MJ_CREATE 0X00 //对应用户层函数CreateFile()
#define IRP_MJ_CLOSE 0X02 //对应用户层函数CloseHandle()
#define IRP_MJ_READ 0X03 //对应用户层函数ReadFile()
#define IRP_MJ_WRITE 0X04 //对应用户层函数WirteFile()
#define IRP_MJ_DEVICE_CONTROL 0X0e //DeviceIoControl()
使用过程:
- 创建IRP处理函数。
- 在驱动入口函数里面DriverEntry()注册处理函数。
- 细化IRP函数。
(1)注册派遣函数
(2)应用程序与驱动通信
在驱动里创建符号链接
通过符号链接与相应驱动程序通信
IRP 是数据请求包的一个简称。当应用程序发起CreateFile或ReadFile API操作设备的时候,就会将相关参数信息封装为一个IRP数据包。通过IoCallDriver传递给驱动程序。
IRP数据结构
typedef struct _IRP {
PMDL MdlAddress;
ULONG Flags;
union {
struct _IRP* MasterIrp;
PVOID SystemBuffer;
} AssociatedIrp;
IO_STATUS_BLOCK IoStatus;
KPROCESSOR_MODE RequestorMode;
BOOLEAN PendingReturned;
BOOLEAN Cancel;
KIRQL CancelIrql;
PDRIVER_CANCEL CancelRoutine;
PVOID UserBuffer;
union {
struct {
union {
KDEVICE_QUEUE_ENTRY DeviceQueueEntry;
struct {
PVOID DriverContext[4];
};
};
PETHREAD Thread;
LIST_ENTRY ListEntry;
} Overlay;
} Tail;
} IRP, *PIRP;
kd> dt nt!_IRP
+0x000 Type : Int2B
+0x002 Size : Uint2B
+0x004 MdlAddress : Ptr32 _MDL
+0x008 Flags : Uint4B
+0x00c AssociatedIrp : <unnamed-tag>
+0x010 ThreadListEntry : _LIST_ENTRY
+0x018 IoStatus : _IO_STATUS_BLOCK
+0x020 RequestorMode : Char
+0x021 PendingReturned : UChar
+0x022 StackCount : Char
+0x023 CurrentLocation : Char
+0x024 Cancel : UChar
+0x025 CancelIrql : UChar
+0x026 ApcEnvironment : Char
+0x027 AllocationFlags : UChar
+0x028 UserIosb : Ptr32 _IO_STATUS_BLOCK
+0x02c UserEvent : Ptr32 _KEVENT
+0x030 Overlay : <unnamed-tag>
+0x038 CancelRoutine : Ptr32 void
+0x03c UserBuffer : Ptr32 Void
+0x040 Tail : <unnamed-tag>
具体含义:
MdlAddress : 是一个MDL的指针,当内核层和用户层采用共享内存的结构传递数据的时候,这个MDL就代表共享的内存信息(共享物理内存,通过MDL映射)。这个成员生效的标记为:DO_DIRECT_IO, METHOD_IN_DIRECT 或者METHOD_OUT_DIRECT.
AssociatedIrp : 这个成员是个联合体,其中存在一个SystemBuffer程序;当内核层使用用户层的数据的时候是通过拷贝数据的方式来实现的话,那么拷贝后的数据就放在了AssociatedIrp.SystemBuffer中了。这个成员生效的标记是DO_BUFFERED_IO或者METHOD_BUFFERED。
IoStatus : 返回的状态信息。
RequestorMode : UserMode或KernelMode,指定原始I/O请求的来源。驱动程序有时需要查看这个值来决定是否要信任某些参数。
PendingReturned : Pending 状态,如果为TRUE,则表明处理该IRP的最低级派遣例程返回了STATUS_PENDING。
StackCount : 设备栈的数目。
CurrentLocation : 当前处于哪个设备栈的索引。
Cancel : IRP是否被取消,如果为TRUE,则表明IoCancelIrp已被调用(该函数用于取消这个请求)。如果为FALSE,则表明没有调用IoCancelIrp函数。
CancelIrql(KIRQL) : 是一个IRQL值,表明那个专用的取消自旋锁是在这个IRQL上获取的.
CancelRoutine(PDRIVER_CANCEL) : 是驱动程序取消例程的地址。你应该使用IoSetCancelRoutine函数设置这个域而不是直接修改该域(因为可以原子修改)。
UserBuffer(PVOID) : 用户层参数的直接地址,设置标记METHOD_NEITHER时候有效。
Tail.Overlay 是Tail联合中的一种联合结构,如下:
图示
应用程序和驱动:
Windows驱动大致分为:
function driver: 设备功能驱动
filter driver: 设备辅助驱动
software driver: 软件模块驱动
bus driver: 总线设备驱动
驱动程序通信:文章来源:https://www.toymoban.com/news/detail-405427.html
https://github.com/G4rb3n/Windows-Driver/tree/master/MT-Communication文章来源地址https://www.toymoban.com/news/detail-405427.html
到了这里,关于【IRP】Windows 驱动之IRP的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!