关于文件系统设备堆栈的说明

学习windows驱动(设备对象设备栈) IO相关的操作是围绕设备对象进行的。设备对象分下几类:1、功能设备对象(FDO): 功能驱动为设备创建一个FDO,在设备栈里它位于物理设备(PDO)的上层。2、物理设备对象(PDO): 总线驱动创建PDO,逻辑上代表物理设备本身,功能设备对象(FDO)代表系统对这个PDO做的处理。FDO为什么会被总线驱动创建?是因为FDO代表的物理设备连接到此总线设备上,总线驱动起了承担总线设备的功能驱动作用。3. 阅读详情

若干关于 file system driver stack

写这个文章的初衷是想知道究竟一个读写文件的irp都是怎样被处理的.....

大家都知道这样的一个读写文件irp是发送给file system的driver的file system把这个irp交给了下层的device

这个device叫logical volume device,它由device的vbp里面的realdevice指针指出(不一定就会是这个device,而应该是这个device所在的stack的最上层的device).那这个device是个什么东西呢?它是怎么来的呢?按照道理,这个irp应该被发送到disk的驱动去才对?那个这个device是disk的驱动创建的么?如果不是,那中间都有些什么步骤呢?

本文就是回答上面这些问题的.

用softice看看就知道file system转发的irp并不是vpb指向的那个device,而是另外一个叫volsnap的driver创建的device. 再跟踪看看,volsnap创建的device是跟vpb的device在同一个stack里面,而且volsnap创建的device的下一个device就是vpb的device.

好了.至少知道了确实file system driver要把irp转发到vpb指向的device去.那接下来呢?irp又会到哪里?

再跟踪下去.irp到了一个由partmgr.sys创建的device里,看看这个partmgr...它是一个disk driver 的filter(多用注册表,当初我在这里花了好长时间才发现这个东西是一个filter),所以partmgr把这个irp转发到了disk driver.disk driver接着发给了acpi.sys,然后acpi.sys转发给了atapi.sys创建的一个device去,看看这个device的stack,已经是1了,irp就到尽头了,接下来的就不是irp的流程了,而是所谓的port/miniport流程了.

大致的把整个的结构过了一次,里面有很多的疑问,下面要一一解释,最好是能用device tree看看这个过程,看看哪些是pdo哪些是fdo,看看每个device的stack值都是多少,自己模范下看看能不能了解irp的流程.

上面的整个irp的流程是很大的.顶层device的stack达到了8,首先你就会奇怪这么庞大一个device stack是怎么建立起来的?

先说最上面的部分
file system在受到一个mount的fs control的时候,创建了一个无名的device,并且保存了vpb 的 realdevice所在的stack的最上层的device,以后所有的irp都转发到这个保存的指针上面.注意这里并没有attach到那个device的stack上面,而是直接使用指针call driver的.这里会有一个问题,在file system mount以后,再attach到volume device的stack上的device 收不到 file system传递过来的irp,至于这个问题怎么解决,msdn里面有说,把这个filter driver设置成启动时加载,至于为什么这样作了就能行,这个在后面会有解释.

在我的机器上,file system保存的device是由volsnap创建的一个filter device,在这个filter device下面是vbp指向的device,它有名字叫HarddiskVolume1(名字不一定就是这个),这个device是一个pdo,注意它是一个pdo,按照常规 pdo的创建不是由系统主导的,而是由driver主导了,它一般不在adddevice里面创建,而是由driver在需要的时候手动创建的.为什么说到这个细节呢?因为我们没有这个driver(名字叫ftdisk.sys)的源代码,在反汇编的时候,明白了这个以后比较有目标,这个ftdisk.sys的代码是非常简单的,ida反汇编一下就发现harddiskv
olumeX这个device并没有attach到什么stack上面(也算是pdo的一般做法),但是这个pdo却保存了两个指针,一个指向另外一个pdo(70h),一个(74h)指向这个pdo的stack的最顶的device,而且以后的irp它都发给了这个device,这个device也就是由partmgr创建的device了.

partmgr其实只是一个filter,挂接到disk driver上面的,那么接下来的stack创建就比较简单了.用device tree向前看,partmgr创建的是一个filter,它attach的device叫dr0,是一个fdo,它对应的pdo叫idedevicepotolo-3,这个部分的过程就根据的容易了,disk driver是有源代码的,仔细看看就能明白其中的创建关系.看清楚了,这个pdo的stack值是1,所以irp到这里就算是尽头了.

再向下又是一个fdo,ideport(atapi.sys),它创建了上面的那个pdo,ideport我没有详细的反汇编分析,不过可以推测得出来,它对应得pdo是ide0channal0,而这个pdo又是由pciide创建的,你可能会注意到中间多了一个filter acpi.sys创建的一个device,也许你会注意到这个acpi.sys到处创建filter.

再往下就是pci,acpi_hal这些device了,他们的行为都很正常.不详细说了(其实是我没有详细的研究,只有些想当然的想法,不敢拿出来说)

到此,回顾下整个device stack,可以看到这里涉及到好多的device stack,irp并没有按照一个stack 走到底.

最上面的是file system的device
|fs filter| <-比如是filemon
|fs volume| <-一般没有名字,由filesystem在mount的时候创建

fs的volume保存有新的stack(partmgr device的stack? 叫这个名字么?)的最上层device的指针,irp转移到这个stack
|volsnap 创建的无名device |
|ftcontrol创建的storage volume device|

这个device有保存有另外一个stack顶层device的指针,irp再次转移
|partmgr创建的无名filter device|
|disk创建的DR0 fdo |
|acpi创建的filter |
|atapi创建的pdo |

这个就是irp的全流程,它经历了3个device stack.

呼呼
吐口气吧.......

本来这个文章写到这里就算完成了....
但是我还有些心得要写出来.这些属于是无心插柳的结果.只是在我跟踪上面这些结果的时候额外的收获.

先看device tree里面,pnp方式查看,你会注意到有很多的pdo属于pnpmanager,但是他们却没有对应的fdo.很奇怪吧,再看这些pdo的名字,你会发现partmgr赫然在目.奇怪了,它怎么有个fdo呢?

首先要明确的就是凡是有填充adddevice域的driver都会对应一个pdo,这个是必然的,因为adddevice传递进来的参数就有一个是pdo,还有一个事情就是在某种情况下,即使不填充adddevice域,pnpmanager还是会创建一个pdo.你所看到的大多少没有fdo的pdo都是这样来的.那什么时候pnpmanager创建这些pdo呢?答案就在系统启动的时候.

你也应该要知道,有些驱动并不是由ntoskrnl加载的,有很多的driver是由loader加载的,win2000 把这些叫做 boot driver.

ntldr加载必要的driver以后,转移控制权给ntoskrnl的入口函数(kiinitsystem是这样么?),经过一定的步骤以后来到了ioinitsystem函数,这个函数作一些初始化以后开始了pnp系统,这里ntoskrnl创建一个pnpmanager的root device,并且start了这个device,然后发送query bus relation,这个时候pnp manager读取注册表一一创建每个需要创建的service的pdo,构造device tree,然后调用每个boot driver的driver entry函数,然后是他的add device函数(实际情况比我上面描述的要复杂得多).

然后pnp就开始了众所周知的enum 工作,这个是委托给worker线程完成的,大部分情况是使用workitem进行的,这个部分显得非常的复杂,跟踪调试非常的不方便(恕我也没有完全的弄明白,先跳过去,以后有机会再详细的讨论这个部分).

跳过了xxx的步骤以后,pnp enum到了主板的南桥芯片(我的是ich4)设备,创建对应的fdo(没有名字,属于pci这个driver),继续enum,得到ich4里面的mass storage controller,创建pdo也是属于pci的,创建对应的fdo,pciide(中间有个acpi的filter加进来,主要进行电源管理),这个fdo再enum,创建两个ide channal的pdo,再创建对应的fdo,ideport(由atapi提供,还是有acpi的filter加进来),ideport再enum机器上的硬盘pdo,继续加载acpi的filter,加载硬盘的fdo,也就是disk.sys了,再加载upperfilter,partmgr.sys.

接下来的事情关键了,硬盘的fdo告诉pnp它的bus relations要更新(可以查看disk.sys的源代码观察这个部分进行的事情),然后pnp发送一个 query bus relations的irp给硬盘pdo所在的stack,这个stack的最上部分并不是硬盘的pdo,也不是acpi的filter,也不是硬盘的fdo,而是partmgr.sys这个driver,它接受到这个irp的时候,安装一个complete routing,然后把irp向下传递,等到控制权再回到手上的时候,partmgr.sys作了一系列的事情,最最重要的就是它发送了一个IO Control irp到另外的一个driver.

接手这个irp的是ftdisk.sys这个driver(指basic volume的情况,如果是dynamic volume的话呢,接受的是dmio.sys这个driver),这个driver然后创建自己的pdo,并且把这个pdo关联(不是attach)到了partmgr.sys所在的stack,实现了上面两个stack之间的关联.这个pdo也加载了自己的fdo,一个叫volsnap.sys提供.

这个irp完成以后,partmgr完成原来的query bus relations irp,可以看到disk.sys创建了若干个pdo,attach到了自己的fdo上面,再这以后,disk所在的stack的top device就不是partmgr.sys了,而是最后一个由disk创建的pdo.而partmgr在系统里面注册了通知消息,它能在以后的volume change的时候得到通知,然后会发送相应的io control irp到ftdisk,然后ftdisk完成更新.

接下来事情又变得简单了,file system driver加载,在遇到第一次访问磁盘的时候,mount到由ftdisk创建的pdo上面去,再次实现两个stack的关联.

上面就是整个过程的大概流程.

明白了这个过程,要实现一个虚拟xx的就容易了.
说说daemon-tools一类的实现方式吧.

他们基本都提供一个bus driver(d343bus.sys),作为一个 boot driver 由ntldr加载到内存,ntoskrnl在适当的时候会调用它的driverentry以及adddevice函数,这两个函数里面分别加载了fdo和创建了自己的pdo,这个pdo的inf文件里面表示它要加载的driver是一个叫d343port.sys的driver,这个driver再在scsiport的帮助下create了一个pdo.这个pdo返回的id很有趣,SCSI//CDRom,SCSI//RAW,这样的话,windows就把它当作了一个cdrom来处理.再向上的fdo,filter都交给windows来操作了.

如果是一个虚拟硬盘呢?你马上就反映过来了,报告pdo的id为Gendisk一类的就ok.

当然实际的实现远不是这么简单的,bus driver,mini port driver都有很多要注意的地方.
(以上大部分属于想象推测,没有经过严格的认证,有错的地方请包涵).

到这里基本上这个文章又结束了.
也许有人要问这些东西是怎么来的?当然是用softice + 2000代码 + ida来的了,唯一要修改的就是要让softice在所有的外部driver的driverentry调用前正常工作.这个方法在驱网的论坛上能找到 

CANopen通信之PDO通信 过程数据对象(Process Data Object,PDO)是用来传输实时数据的,提供对设备应用对象的直接访问通道,它用来传输实时短帧数据,具有较高的优先权。 立即下载

相关推荐

ETL数据集成案例

一个典型的ETL数据集成案例是将多个来源的数据合并成一个数据集。假设有一个公司,该公司使用一些不同的系统来存储不同部门的数据,例如销售数据存储在一个CRM系统中,财务数据存储在一个ERP系统中,人力资源数据存储在一个HR系统中。为了更好地进行报告和分析,该公司决定将所有这些数据集成到一个数据仓库中。以下是实现这一目标的ETL过程的步骤:提取(Extract):首先,需要从每个系统中提取所需的数据。每个系统可能有不同的数据格式和结构,因此需要编写不同的提取程序或查询来提取数据。

runqu的博客 948

jdk问题定位工具箱-线程挂死、堆栈满问题定位

1-前言 开发过程中,偶尔会遇到一些线程池占满、cpu使用过高、堆栈满了的问题,需要进一步分析线程具体位置,从而做进一步分析,现将linux和jdk自带的一些线程调试手段总结如下,供用户尽一份分析。 更多内容: 2- 定位手段 2.1java visualVM图形化工具 linux控制器后天敲入命令jvisualvm,可以打开jdk自带的图形化调试和分析工具,通过此工具,可以看到当前运行的所有jd...

642

java modbus通讯协议_Modbus通 讯 协 议

电磁流量计Modbus通 讯 协 议(版本号:9000-K V9.1.1)2020年01月01日通讯协议针对KFD电磁流量计工业应用设计,版本:9000-K V9.1.1,该版本主要用于实时数据采集、流量测量、流量累计控制及部分参数的修改。一、主机系统通讯部件要求1.国际标准RS-485通讯接口部件,不小于11Bytes 的通信缓冲区(FIFO),支持1200、2400、4800、96...

weixin_39956612的博客 1012

Windows驱动程序设计(三)

第四章 驱动程序的基本结构 数据结构是计算机控制程序的核心,I/O 管理器定义了一些数据结构,这些数据结构式编写驱动程序锁必须掌握的。 Windows驱动程序中重要的数据结构 驱动对象(DRIVER_OBJECT) 每个驱动程序会有唯一的驱动对象与之一一对应,并且这个驱动对象是在驱动加载时候被内核中的对象管理器程序创建的。去东方对象用DRIVER_OBJECT数据结构表示: type

dabenxiong的专栏 1211

SECS/GEM EAP 设备自动化功能原理和设计方案

半导体SECS GEMEAP实现了对生产线上机台的实时监控,是工厂自动化不可缺少的控制系统。EAP系统与FAB中的机台紧密相关,系统的设计与开发必须与生产线的机台实际生产流程相一致,才能达到控制机台生产的目的。 EAP SECS/GEM是MES与设备的桥梁,EAP通过SECS国际标准协议与机台进行数据传输。SECS是半导体设备(半导体行业称设备为机台)必须遵循的一种国际通信协议。EAP就是通过SECS与设备通信、传输数据、发送指令控制设备按照预先定义........

semisecs 17万+

避开这些坑,你的Python爬虫才能稳定爬取IEEE Xplore(含反爬策略与MongoDB存储实战)

本文详细介绍了如何构建稳定的Python爬虫系统以爬取IEEE Xplore学术论文,包括反爬策略、MongoDB存储优化和断点续传机制。通过动态等待时间算法、请求头指纹管理和会话保持策略,有效应对IEEE的反爬机制。同时,优化MongoDB数据结构和索引,提升存储效率。最后,强调法律合规与伦理考量,确保爬虫合法合规运行。

weixin_29031057的博客 1096

windows 内核原理与实现读书笔记之驱动程序初始化

I/O系统的初始化是在内核的阶段1初始化过程中完成的。主要函数是Phase1InitializationDiscard,它调用IoInitSystem 来初始化I/O系统。 IoInitSystem 初始化工作: 调用IopCreateObjectTypes ,创建7种类型对象:Adapter、DeviceHandler、Controller、Device、Driver、IoCompletion、File,并存放在相应的全局变量中。 WRK中的全局类型对象变量,如下表: CmpKeyObjec

maomao171314的专栏 1366

地平线旭日X3派(RDK X3)从开箱到联网:新手避坑指南

本文为地平线旭日X3派(RDK X3)新手提供从开箱到联网的完整避坑指南。详细讲解了硬件识别、系统镜像烧录、串口调试(波特率921600)、有线/无线网络配置以及SSH/VNC远程访问等关键步骤,帮助开发者快速搭建稳定的开发环境,为后续AI应用部署扫清障碍。

weixin_29174385的博客 953

Cubemx文件系统挂载多设备

这样就有一个问题,由于我们自己编写底层驱动函数时如果涉及到多个不同存储设备的使用,那么我们往往会在user_diskio.c中通过传入的参数pdrv结合switch判断来切换不同的存储设备底层驱动,这里传入的参数pdrv为该设备对应的lun参数,但我们看到FATFS_LinkDriver(const Diskio_drvTypeDef *drv, char *path)设备驱动绑定函数时都默认lun参数为0,因此当用switch对存储设备底层驱动进行切换时,如果case的值不为0就不会执行其中的代码。

qq_48211392的博客 2317

RK3568 低功耗设计全解析:DVFS 策略与 PMIC 电源管理

本文深入解析RK3568处理器的低功耗优化方案。从硬件架构分析入手,阐述四核Cortex-A55的功耗特性及分层电源域设计。重点介绍DVFS动态调压调频技术,包括Linux内核配置方法及场景化策略设计。详细讲解RK809 PMIC的电源管理优化,提供外设电源域控制与休眠唤醒配置的实战案例。通过智能终端应用实例,展示待机功耗从280mA降至65mA的优化效果,并推荐功率测试工具。文章强调需要平衡性能与功耗,结合场景定制策略,并指出AI负载预测等未来优化方向,为RK3568开发者提供系统性的低功耗解决方案。

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 2074

OSCP-Challenge 2 - Relia

使用andrea:PasswordPassword_6登录远程桌面,在c盘根目录下发现一个计划任务的ps,文件,修改执行的exe位木马,获取到milana用户的反弹shell。,发现开放了一个8000端口,但是我们外部是访问不到的,它对应的页面是/var/www/internal/,这个目录下的文件我们是可以访问的,把这个文件打个包放到本地分析下。其中数据的可以直接连接mssql,但是端口是49965,不过在数据库中没发现什么可用的信息,但是可以修改密码直接进后台,这个可以先放放。

羽的博客 7777

GFS分布式文件系统

GlusterFS 是一个开源的分布式文件系统,它将多个物理存储设备整合为一个统一的存储池,通过网络向外提供文件存储服务。它基于标准的 Linux 操作系统和通用的硬件设备构建,不依赖于专用硬件,具有高度的灵活性和可扩展性。GlusterFS 支持多种客户端,包括 Linux、Windows、macOS 等,并且可以与多种应用程序无缝集成,如虚拟化平台(KVM、VMware)、数据库(MySQL、PostgreSQL)等,广泛应用于大数据存储、云计算、内容分发网络等领域。

2502_91448199的博客 1390

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Wrapfs : a stackable file system(一种堆栈式文件系统)

wrapfs

Fybon的专栏 6885

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

UBI 文件系统

UBIFS 文件系统代表 UBI 文件系统。UBI 代表“未分类的块映像”。UBIFS 是一种闪存文件系统,这意味着它设计用于闪存设备。重要的是要理解,UBIFS 与 Linux 中的任何传统文件系统(如 Ext2、XFS、JFS 等)完全不同。UBIFS 代表一种单独的文件系统类,它与 MTD 设备(而不是块设备)一起工作。此类的另一个Linux 文件系统是 JFFS2。为了更清楚起见,这里对 MTD 设备和块设备进行了一个小的比较。很明显,UBIFS 与传统文件系统有很大不同。

qq_37255138的博客 1643

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

GFS 分布式文件系统

GlusterFS 是一个开源的分布式文件系统。由存储服务器、客户端以及NFS/Samba 存储网关(可选,根据需要选择使用)组成。没有元数据服务器组件,这有助于提升整个系统的性能、可靠性和稳定性。MFS传统的分布式文件系统大多通过元服务器来存储元数据,元数据包含存储节点上的目录信息、目录结构等。这样的设计在浏览目录时效率高,但是也存在一些缺陷,例如单点故障。一旦元数据服务器出现故障,即使节点具备再高的冗余性,整个存储系统也将崩溃。

2301_81307988的博客 860

RHEL 存储堆栈完全解析:从硬件到应用的存储管理指南

本文系统介绍了Linux存储堆栈的组成架构和管理实践。存储堆栈采用分层设计,包括块设备层(SCSI/SAS/NVMe等)、冗余层(多路径、RAID)、管理层(分区、LVM)、功能层(加密/压缩)和Stratis简化管理层。重点讲解了LVM的三层架构(物理卷→卷组→逻辑卷)及其高级功能如LUKS加密和VDO优化,以及Stratis的存储池、精简配置和快照特性。文章提供了存储组件选型建议和监控维护最佳实践,展示了从底层硬件到上层应用的完整存储解决方案。

m0_73892800的博客 623

Linux文件系统初识

一、为啥要认识文件系统        在学习一个新的知识之前,要么先了解它的作用是什么,或者它的意义是啥,这样才能带着目的去学习,文件系统也是一样的。        都说Linux系统一切皆文件,可知文件系统的必要性。比如说之前使用 wiringPi 库可以让让我们简单的操作树莓派的IO口和一些外设,但是如果不用 wiringPi 库,我们就需要写一些驱动文件来使用配置

qq1140920745的博客 260

文件系统过滤驱动开发(二)

<br />    声明:高手请一笑而过.>_<<br /> <br />    文件系统过滤驱动开发(一)里面已经讲了文件系统过滤驱动绑定设备的大概思路,剩下的就是一些细节处理部分.<br /> <br />    首先说说fast I/O派遣函数,我们知道,IRP是默认的I/O请求处理机制,IRP可以用于同步或者异步I/O,也可以用于缓存和非缓存I/O,同时还可以用于分页I/O.内存管理器通过发送合适的IRP到文件系统以处理缺页错误.快速I/O是是特别设计用于缓存文件的快速同步I/O.在快速I/O操作中

GaA.Ra的自留地 in Csdn 2593

linux文件系统-特殊文件系统/proc

早期的Unix在设备文件目录/dev下设置了一个特殊文件,称为/dev/mem。通过这个文件可以读写系统的整个物理内存,而物理内存的地址就用读写文件内部的位移量。这个特殊文件同样适用于read、write、lseek等常规的文件操作,从而提供了一个在内核外部动态地读写包括内核映像和内核中各个数据结构以及堆栈内容的手段。这个手段既可以用于收集状态信息和统计信息,也可以用于程序调试,还可以动态地给内核打补丁或者改变一些数据结构或变量的内容。采用虚存以后,Unix又增加了一个特殊文件/dev/kmem,对应于系统

guoguangwu的专栏 1135
上一篇: 第三方二进制汇编代码在VC中的移植和应用
下一篇: 在文件过滤驱动中如何判断文件访问请求来自网络
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值