C++第三十九篇 -- 研究一下Windows驱动开发(二)-- 驱动程序中重要的数据结构
数据结构是计算机程序的核心,I/O管理器定义了一些数据结构,这些数据结构是编写驱动程序时所必须掌握的。驱动程序经常要创建和维护这些数据结构的实例。
一、驱动对象(DRIVER_OBJECT)
每个驱动程序会有唯一的驱动对象与之对应,并且这个驱动对象是在驱动加载的时候,被内核中的对象管理程序所创建的。
驱动对象用DRIVER_OBJECT数据结构表示,它作为驱动的一个实例被内核加载,并且内核对一个驱动只加载一个实例。确切地说,是由内核中的I/O管理器负责加载的。驱动程序需要在DriverEntry中初始化。先了解一下驱动对象的数据结构。
》DeviceObject:每个驱动程序会有一个或多个设备对象。其中,每个设备对象都有一个指针指向下一个驱动对象。通过DeviceObject,就可以遍历驱动对象里的所有设备对象。设备对象是由程序员自己创建的,而非操作系统完成,在驱动被卸载的时候,遍历每个设备对象,并将其删除。
》DriverName:顾名思义,PriveName记录的是驱动程序的名字。这里用UNICODE字符串记录,该字符串一般为\Driver\[驱动程序名称]。
》HardwareDatabase:这里记录的是设备的硬件数据库键名,这里同样用UNICODE字符串记录。该字符串一般为\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM。
》DriverStartIo:记录StartIo例程的函数地址,用于串行化操作。
》DriverUnload:指定驱动卸载时所用的回调函数地址。
》MajorFunction:MajorFunction域记录的是一个函数指针数组,也就是MajorFunction是一个数组,数组中的每个成员记录着一个指针,每一个指针指向的是一个函数。这个函数就是处理IRP的派遣函数。
》FastIoDispatch:文件驱动中用到的派遣函数,参阅MSDN。
二、设备对象(DEVICE_OBJECT)

每个驱动程序会创建一个或多个设备对象,用DEVICE_OBJECT数据结构表示。每个设备对象都会有一个指针指向下一个设备对象,因此就形成了一个设备链。设备对象保存设备特征和状态的信息。
》DriverObject:指向驱动程序中的驱动独享。同属于一个驱动程序的驱动对象指向的是统一驱动对象。
》NextDevice:指向下一个设备对象。这里指的下一个设备对象是同属于一个驱动对象的设备,也就是同一个驱动程序创建的若干设备对象。每个设备对象根据NextDevice域形成链表,从而可以枚举每个设备对象。
》AttachedDevice:指向下一个设备对象。这里指的是,如果有更高一层的驱动附加到这个驱动的时候,AttachedDevice指向的就是那个更高一层的驱动。
》CurrentIrp:在使用StartIO例程的时候,此域指向的是当前IRP结构。
》Flags:此域是一个32位的无符号整型。每一个位有具体的含义。
| 标志 | 描述 |
| DO_BUFFERED_IO | 读写操作使用缓冲方式(系统复制缓冲区)访问用户模式数据 |
| DO_EXCLUSIVE | 一次只允许一个线程打开设备句柄 |
| DO_DIRECT_IO | 读写操作使用直接方式(内存描述符表)访问用户模式数据 |
| DO_DEVICE_INITIALIZING | 设备对象正在初始化 |
| DO_POWER_PAGABLE | 必须在PASSIVE_LEVEL级上处理IRP_MJ_PNP请求 |
| DO_POWER_INRUSH | 设备上电期间需要大电流 |
》DeviceExtension:指向的是设备的扩展对象。每个设备都会制定一个设备扩展对象,设备扩展对象记录的是设备自己特殊意义的结构体,也就是程序员自己定义的结构体。另外,在驱动程序中,应该尽量避免全局变量的使用,因为全局变量涉及不容易同步的问题。解决办法,将全局变量存在设备扩展里。
》DeviceType:指明设备的类型。
| 设备类型 | 描述 |
| FILE_DEVICE_BEEP | 蜂鸣器设备对象 |
| FILE_DEVICE_CD_ROM | CD光驱设备对象 |
| FILE_DEVICE_CD_ROM_FILE_SYSTEM | CD光驱文件系统设备对象 |
| FILE_DEVICE_CONTROLLER | 控制器设备对象 |
| FILE_DEVICE_DATALINK | 数据链设备对象 |
| FILE_DEVICE_DFS | DFS设备对象 |
| FILE_DEVICE_DISK | 磁盘设备对象 |
| FILE_DEVICE_DISK_FILE_SYSTEM | 磁盘文件系统设备对象 |
| FILE_DEVICE_FILE_SYSTEM | 文件系统设备对象 |
| FILE_DEVICE_INPORT_PORT | 输入端口设备对象 |
| FILE_DEVICE_KEYBOARD | 键盘设备对象 |
| FILE_DEVICE_MAILSLOT | 邮件槽设备对象 |
| FILE_DEVICE_MIDI_IN | MIDI输入设备对象 |
| FILE_DEVICE_MIDI_OUT | MIDI输出设备对象 |
| FILE_DEVICE_MOUSE | 鼠标设备对象 |
| FILE_DEVICE_MULTI_UNC_PROVIDER | 多UNC设备对象 |
| FILE_DEVICE_NAMED_PIPE | 命名管道设备对象 |
| FILE_DEVICE_NETWORK | 网络设备对象 |
| FILE_DEVICE_NETWORK_BROWSER | 网络浏览器涉笔对象 |
| FILE_DEVICE_NETWORK_FILE_SYSTEM | 网络文件系统设备对象 |
| FILE_DEVICE_NULL | 空设备对象 |
| FILE_DEVICE_PARALLEL_PORT | 并口设备对象 |
| FILE_DEVICE_PHYSICAL_NETCARD | 物理网卡设备对象 |
| FILE_DEVICE_PRINTER | 打印机设备对象 |
| FILE_DEVICE_SCANNER | 扫描仪设备对象 |
| FILE_DEVICE_SERIAL_MOUSE_PORT | 串口鼠标设备对象 |
| FILE_DEVICE_SERIAL_PORT | 串口设备对象 |
| FILE_DEVICE_SCREEN | 屏幕设备对象 |
| FILE_DEVICE_SOUND | 声音设备对象 |
| FILE_DEVICE_STREAMS | 流设备对象 |
| FILE_DEVICE_TAPE | 磁带设备对象 |
| FILE_DEVICE_TAPE_FILE_SYSTEM | 磁带文件系统设备对象 |
| FILE_DEVICE_TEANSPORT | 传输设备对象 |
| FILE_DEVICE_UNKNOWN | 未知设备对象 |
| FILE_DEVICE_VIDEO | 视频设备对象 |
| FILE_DEVICE_VIRTUAL_DISK | 虚拟磁盘设备对象 |
| FILE_DEVICE_WAVE_OUT | 声音输出设备对象 |
| FILE_DEVICE_8042_PORT | 8042端口设备对象 |
| FILE_DEVICE_NETWORK_REDIRECTOR | 网卡设备对象 |
| FILE_DEVICE_BATTERY | 电池设备对象 |
| FILE_DEVICE_BUS_EXTENDER | 总线扩展设备对象 |
| FILE_DEVICE_MODEM | 调制解调器设备对象 |
| FILE_DEVICE_VDM | VDM设备对象 |
| FILE_DEVICE_MASS_STORAGE | 大容量存储设备对象 |
| FILE_DEVICE_SMB | SMB设备对象 |
| FILE_DEVICE_KS | 内核流设备对象 |
| FILE_DEVICE_CHANGER | 充电设备对象 |
| FILE_DEVICE_SMARTCARD | 智能卡设备对象 |
| FILE_DEVICE_ACPI | ACPI设备对象 |
| FILE_DEVICE_DVD | DVD设备对象 |
| FILE_DEVICE_WAVE_IN | 声音输入设备对象 |
根据设备的需要,需要填写相应的设备类型。当制作虚拟设备时,应选择FILE_DEVICE_UNKNOWN类型的设备。
》StackSize:在多层驱动情况下,驱动与驱动之间会形成类似堆栈的结构。IRP会依次从最高层传递到最底层。StackSize描述的就是这个层数。
》AlignmentRequirement:设备在大容量传输的时候,需要内存对齐,以保证传输速度。
三、设备扩展
设备对象记录“通用”设备的信息,而另外一些“特殊”信息记录在设备扩展里。各个设备扩展由程序员自己定义,每个设备的设备扩展也不尽相同。设备扩展是由指定内容和大小,由I/O管理器创建的,并保存在非分页内存中。
在驱动程序中,尽量避免使用全局函数,因为全局函数往往导致函数的不可重入性。重入性指的是,在多线程的程序中,多个函数并行运行,函数的运行结果不会根据函数的调用先后顺序而导致不同。解决的办法是,将全局变量以设备扩展的形式存储,并加以适当的同步保护措施。除此之外,在设备扩展中,还会记录下列一些内容:
》设备对象的反向指针。
》设备状态或驱动环境信息。
》中断对象指针。
》控制器对象指针。
由于设备扩展是驱动程序专用的,它的结构必须在驱动程序的头文件中定义。
C++第三十九篇 -- 研究一下Windows驱动开发(二)-- 驱动程序中重要的数据结构的更多相关文章
- C++第三十八篇 -- 研究一下Windows驱动开发(二)--WDM式驱动的加载
基于Windows驱动开发技术详解这本书 一.简单的INF文件剖析 INF文件是一个文本文件,由若干个节(Section)组成.每个节的名称用一个方括号指示,紧接着方括号后面的就是节内容.每一行就是一 ...
- C++第三十三篇 -- 研究一下Windows驱动开发(一)内部构造介绍
因为工作原因,需要做一些与网卡有关的测试,其中涉及到了驱动这一块的知识,虽然程序可以运行,但是不搞清楚,心里总是不安,觉得没理解清楚.因此想看一下驱动开发.查了很多资料,看到有人推荐Windows驱动 ...
- C++第四十篇 -- 研究一下Windows驱动开发(三)-- NT式驱动的基本结构
对于NT式驱动来说,主要的函数是DriverEntry例程.卸载例程及各个IRP的派遣例程. 一.驱动加载过程与驱动入口函数(DriverEntry) 和编写普通应用程序一样,驱动程序有个入口函数,也 ...
- C++第三十五篇 -- 写第一个驱动开发程序
VS2017+WDK+VMware12+Win10环境配置完毕,接下来写第一个驱动程序. 1.新建一个KMDF的程序. 2.配置项目属性. 3.编译项目.一般这里应该成功,我一台电脑成功了,另一台电脑 ...
- Android UI开发第三十九篇——Tab界面实现汇总及比较
Tab布局是iOS的经典布局,Android应用中也有大量应用,前面也写过Android中TAb的实现,<Android UI开发第十八篇——ActivityGroup实现tab功能>.这 ...
- 学习之路三十九:新手学习 - Windows API
来到了新公司,一开始就要做个程序去获取另外一个程序里的数据,哇,挑战性很大. 经过两周的学习,终于搞定,主要还是对Windows API有了更多的了解. 文中所有的消息常量,API,结构体都整理出来了 ...
- 第三十九篇-RecyclerView的使用
RecyclerView介绍 RecyclerView的出现可以替代ListView,并且比ListView更高级且更具灵活性.如果有数据集合,其中的元素将因用户操作或网络事件而在运行时发生改变,请使 ...
- 第三十九篇 Python异常处理
一. 什么是异常 异常就是程序运行时发生的错误,在程序出现错误时,则会产生一个异常,若程序没有处理它,则会抛出该异常,程序的运行也随之终止,在python中,错误触发的异常如下 错误分成两种: #语法 ...
- 第三十九篇:Vue3 watch(ref和reactive的监视)
好家伙, 1.vue2中的watch是调用配置项,(只能写一个) vue3中的watch是一个函数(可以写很多个) 2.watch一些用法: 这里是定义的数据 set up(){ let sum =r ...
随机推荐
- 【逆向实战】ES文件浏览器未授权访问漏洞(CVE-2019-6447)具体分析及利用
/作者:Kali_MG1937 CSDN博客号:ALDYS4 QQ:3496925334 未经许可,禁止转载/ 漏洞简介 CVE-2019-6447是Android端上的一个知名软件:ES文件浏览器的 ...
- Django基础之自定义分页器
自定义分页器 针对批量插入的数据,我们在前端展示的时候发现一个很严重的问题,一页展示了所有的数据,数据量太大,查看不方便 针对数据量大但又需要全部展示给用户观看的情况下,我们统一做法都是做分页处理 分 ...
- SpringMVC 进阶版
请求限制 一些情况下我们可能需要对请求进行限制,比如仅允许POST,GET等... RequestMapping注解中提供了多个参数用于添加请求的限制条件 value 请求地址 path 请求地址 m ...
- 【题解】coin HDU2884 多重背包
题目 Coins Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- TKE 体验升级:更快上手 K8s 的24个小技巧
作者 王孝威,腾讯云容器产品经理,热衷于为客户提供高效的 Kubernetes 使用方式,为客户极致降本增效服务. 背景 "功能"解决是产品有或者没有一个能力的问题,有了" ...
- 从0到1用react+antd+redux搭建一个开箱即用的企业级管理后台系列(基础篇)
背景 最近因为要做一个新的管理后台项目,新公司大部分是用vue写的,技术栈这块也是想切到react上面来,所以,这次从0到1重新搭建一个react项目架子,需要考虑的东西的很多,包括目录结构.代码 ...
- 进程与线程 .Net Core系列-多线程
进程与线程 进程: 狭义定义:进程是正在运行的程序的实例 广义定义:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动.它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分 ...
- android悬浮窗口
悬浮窗原理 做过悬浮窗功能的人都知道, 要想显示悬浮窗, 要有一个服务运行在后台, 通过getSystemService(Context.WINDOW_SERVICE)拿到WindowManager, ...
- Kubernetes ConfigMap详解,多种方式创建、多种方式使用
我最新最全的文章都在南瓜慢说 www.pkslow.com,欢迎大家来喝茶! 1 简介 配置是程序绕不开的话题,在Kubernetes中使用ConfigMap来配置,它本质其实就是键值对.本文讲解如何 ...
- JAVA 类修饰符
JAVA类的修饰符主要有public,default,protected,private,final,abstract,static 其中外部类中用到的只有public,final,abstract或 ...