Windows内核-7-(IRP)I/O请求包
Windows内核-7-(IRP)I/O请求包
IRP(I/O Request Packet)就是一个进行I/O操作的请求包。
IRP是一个结构体,谁分配谁就得释放,通常由执行体里的管理器,获取内核驱动程序来分配。
IRP不是单独的,只要创建了IRP就会跟着创建IRP的I/O栈,有一个栈是给内核驱动用的:
驱动需要调用IoGetCurrentIrpStackLocation函数来获取内驱驱动对应的I/O栈。
I/O传递
I/O系统是以设备对象为中心,而不是以驱动对象为中心的。IRP可以在设备对象中传来传去:
有点类似于计算机网络的体系结构。但是不可否认的是I/O可以在设备直接进行各种传递,所以通常用来作为读取文本数据。
具体的传递过程有点类似于栈。
IRP和I/O栈
这张图是对前面第一张图的细化。
分发例程(dispatch routine)
IRP最主要的一个作用就是拿来做分发例程,其实也就是分发的实例函数,就是对文件数据的传递。在我的理解里,就是对信息的分发,让大家一起用到数据。
所有的分发例程都有一个原型:
typedef NTSTATUS DRIVER_DISPATCH (
_In_ PDEVICE_OBJECT DeviceObject,
_Inout_ PIRP Irp);
分发例程必须保存在驱动对象的MajorFunction里面,且需要对应和驱动的连接状态:
状态 | 描述 |
---|---|
IRP_MJ_CREATE | 获取文件句柄,对应User下的CreateFile |
IRP_MJ_CLOSE | 关闭文件句柄,对应User下的CloseHandle |
IRP_MJ_READ | 对应ReadFile |
IRP_MJ_WRITE | 对应WriteFile |
IRP_MJ_DEVICE_CONTROL | 对应DeviceIoControl,即可读又可写 |
IRP_MJ_INTERNAL_DEVICE_CONTROL | 和IRP_MJ_DEVICE_CONTROL差不多,但是只有Kernel可用 |
完成请求
一旦决定要处理IRP(意味着不会把该IRP传递给下一个设备对象),就必须要完成它。
比如:
NTSTATUS MyDispatchRoutine(PDEVICE_OBJECT, PIRP Irp) {
//...
Irp->IoStatus.Status = STATUS_XXX;
Irp->IoStatus.Information = NumberOfBytesTransfered; // depends on request type
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_XXX;
}
//这里的IoCompleteRequest就是必须的
安全IRP操作
由于线程原因,很有可能一个去读一个去写,导致两个只有一个拿到了想要的数据。
还有页面内存的原因,修改的时候有可能一起修改了。
内核提供了两种比较安全的处理方式:
1 缓冲I/O
2 直接I/O
缓冲I/O
要使用缓冲I/O只需要在设备对象的Flag字段里面添加一个DO_BUFFERED_IO
DeviceObject->Flags |= DO_BUFFERED_IO
缓冲I/O的原理就是在系统内存中开辟一段缓冲区,作为一个中间人。
比如说要写,就先把内容写到系统内存缓冲区里,然后系统内存缓冲区再写入/读取到缓冲区里面。
直接I/O
直接缓冲采用物理内存映射来处理,将User和Kernel的缓冲区都指向物理内存里面,并且锁定在内存里,然后读写都采用它。这样的好处是减少了调用的开销。但是占了部分内存。
IRP_MJ_DEVICE_CONTROL 调度
前面的缓冲和直接I/O是读或写操作,这里的IRP_MJ_DEVICE_CONTROL操作是基于控制代码来选择读或写两个都可以的。
User态的IRP_MJ_DEVICE_CONTROL 和Kernel态的调用函数原型差不多:
BOOL DeviceIoControl(
HANDLE hDevice,
DWORD dwIoControlCode,
LPVOID lpInBuffer,
DWORD nInBufferSize,
LPVOID lpOutBuffer,
DWORD nOutBufferSize,
LPDWORD lpBytesReturned,
LPOVERLAPPED lpOverlapped
);
dwIoControlCode:控制代码,由CTL_CODE宏的四个参数来处理。
Zero驱动程序
Client+Kernel的一个练手项目:
对于读请求,会将提供的缓冲区清零然后输出
对于写请求,会把缓冲区消耗掉
源代码zodiacon/windowskernelprogrammingbook: The Windows Kernel Programming book samples (github.com)
最新文章
- 利用office2010 word2010生成目录
- wget: unable to resolve host address 解决办法
- MSSQL 问题集锦
- MMAP和DIRECT IO区别【转】
- Asp.Net Mvc5新特性
- SQL Server 向堆表中插入数据的过程
- 主从集群搭建及容灾部署redis
- Hibernate 集合映射 一对多多对一 inverse属性 + cascade级联属性 多对多 一对一 关系映射
- VMware 下的CentOS6.7 虚拟机与Windows7通信
- python类定义
- 我的Spring Boot学习记录(一):自动配置的大致调用过程
- KVO原理解析
- Struts2之ValueStack、ActionContext
- loadrunner基础学习笔记六-运行负载
- ie8以下兼容圆角等css3的属性
- android的四种线程池
- On the internet, nobody known you are a dog !
- MySQL-视图View
- vcftools安装与使用
- 使用Excel2007去反复功能时要注意的一个问题