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)

Windows内核-7-(IRP)I/O请求包的更多相关文章

  1. 《天书夜读:从汇编语言到windows内核编程》六 驱动、设备、与请求

    1)跳入到基础篇的内核编程第7章,驱动入口函数DriverEnter的返回值决定驱动程序是否加载成功,当打算反汇编阅读驱动内核程序时,可寻找该位置. 2)DRIVER_OBJECT下的派遣函数(分发函 ...

  2. Windows环境中,通过Charles工具,抓取安卓手机、苹果手机中APP应用的http、https请求包信息

    Windows环境中,通过Charles工具,抓取安卓手机.苹果手机中APP应用的http.https请求包信息1.抓取安卓手机中APP应用的http请求包信息1)在电脑上操作,查看Windows机器 ...

  3. windows内核驱动内存管理之Lookaside使用

    Windows内存管理中使用了类似于容器的东西,叫做Lookaside对象,每次程序员申请内存都会从Lookaside里面申请,只有不足的时候,Lookaside才会向内存又一次申请内存空间,这样减少 ...

  4. [14]Windows内核情景分析 --- 文件系统

    文件系统 一台机器上可以安装很多物理介质来存放资料(如磁盘.光盘.软盘.U盘等).各种物理介质千差万别,都配备有各自的驱动程序,为了统一地访问这些物理介质,windows设计了文件系统机制.应用程序要 ...

  5. Windows内核原理-同步IO与异步IO

    目录 Windows内核原理-同步IO与异步IO 背景 目的 I/O 同步I/O 异步I/O I/O完成通知 总结 参考文档 Windows内核原理-同步IO与异步IO 背景 在前段时间检查异常连接导 ...

  6. Windows驱动开发-IRP结构体

    IRP的全名是I/O Request Package,即输入输出请求包,它是Windows内核中的一种非常重要的数据结构. 上层应用程序与底层驱动程序通信时,应用程序会发出I/O请求,操作系统将相应的 ...

  7. Windows内核-7-IRP和派遣函数

    Windows内核-7-IRP和派遣函数 IRP以及派遣函数是Windows中非常重要的概念.IRP 是I/O Request Pocket的简称,意思是I/O操作的请求包,Windows中所有Use ...

  8. 【windwos 操作系统】关键的Windows内核数据结构一览(下)

    I/O管理器 nt!_IRP IRP表示一个I/O请求包结构体,它用来封装执行一个特定I/O操作所需要的所有参数以及I/O操作的状态.IRP的表现也类似于一个线程独立调用栈因此它可以从一个线程传递到另 ...

  9. Windows内核 WDM驱动程序的基本结构和实例

    WDM驱动的基本结构: WDM驱动模型是建立在NT式驱动程序模型基础之上的.对于WDM驱动程序来说,一般都是基于分层的,即完成一个设备的操作,至少要由两个驱动设备共同完成. 1)物理设备对象和功能设备 ...

随机推荐

  1. XCTF getit

    一.查壳 是linux的文件.没加壳 二.拖入ida 分析一下逻辑,发现就是t的值就是flag. 写个exp就出来了. 三.exp分享 s='c61b68366edeb7bdce3c6820314b7 ...

  2. TransE 算法学习笔记

    http://yaoleo.github.io/2017/10/27/TransE算法的理解/ tranE是在模型中嵌入知识图谱等三元组类的一个方法,就像是句子利用词典嵌入一样.

  3. 「BZOJ2839」集合计数

    「BZOJ2839」集合计数 题目大意: 一个包含 \(n\) 个数的集合有 \(2^n\) 个子集,从这些子集中取出若干个集合(至少一个),使他们的交集的元素个数恰好为 \(k\),求方案数,答案对 ...

  4. C语言:FILE p和FILE *p

    FILE p和FILE *p大概可以这么理解:1 . 前一个p指文件型变量,后一个p指文件地址型变量.2 . 前一个p的内存地址已定,后一个p内存地址未定. 前一个是声明类对象,后一个是声明一个可指向 ...

  5. LeetCode解题记录(双指针专题)

    1. 算法解释 双指针主要用于遍历数组,两个指针指向不同的元素,从而协同完成任务.也可以延伸到多个数组的多个指针. 若两个指针指向同一数组,遍历方向相同且不会相交,则也称为滑动窗口(两个指针包围的区域 ...

  6. 开源桌面快速启动工具-GeekDesk

    GeekDesk 小巧.美观的桌面快速启动工具 开发框架 wpf .net 4.7.2 HandyControl 全局热键 鼠标跟随 快速启动 随时随地 支持自定义热键 支持鼠标跟随 自定义壁纸 随意 ...

  7. Python (paramiko) 连接Linux服务器

    目录 参考资料 Paramiko 安装 连接Linux 文件上传/下载 文件封装 其他 参考资料 https://www.liujiangblog.com/blog/15/ https://blog. ...

  8. 每天五分钟Go - 数组

    //数组的声明,默认为0值 var a1 [2]int fmt.Println(a1) //数组的长度 fmt.Println(len(a1)) //遍历数组 for i, v := range a1 ...

  9. Xshell记录Linux连接操作日志遇到的坑

    1.问题描述: 在Windows上,以前一直使用Secure CRT连接Linux主机进行远程操作,使用CRT的日志功能记录连接过程中的所有操作以及输出. 最近(2019-8-17)使用Xshell进 ...

  10. python---replace函数

    描述 Python replace() 方法把字符串中的 old(旧字符串) 替换成 new(新字符串),如果指定第三个参数max,则替换不超过 max 次. 语法 replace()方法语法: st ...