加入收藏 | 设为首页 | 会员中心 | 我要投稿 应用网_丽江站长网 (http://www.0888zz.com/)- 科技、建站、数据工具、云上网络、机器学习!
当前位置: 首页 > 服务器 > 系统 > 正文

04内核-驱动对象

发布时间:2021-03-05 09:14:53 所属栏目:系统 来源:网络整理
导读:副标题#e# 驱动对象 驱动程序:就是一个 .sys 模块, 驱动对象:则是 .sys 被加载到内核中的实例化出来的对象,用于表示这个驱动模块. Windows内核使用 DRIVER_OBJECT 结构体来描述一个驱动对象. 虽然Windows内核源码使用C语言编写,但也使用了面向对象的思想.
副标题[/!--empirenews.page--]


驱动对象

驱动程序:就是一个.sys模块,

驱动对象:则是.sys被加载到内核中的实例化出来的对象,用于表示这个驱动模块.

Windows内核使用DRIVER_OBJECT结构体来描述一个驱动对象.

虽然Windows内核源码使用C语言编写,但也使用了面向对象的思想. 在面向对象思想中,有父类,抽象类,纯虚函数的概念,纯虚函数就是一个类中无须定义的虚函数. 拥有这个函数的类被称为抽象类,继承抽象类的子类必须实现纯虚函数.

DRIVER_OBJECT这个结构体中,它相当于一个类. 类中有几个字段是函数指针,这些函数指针能够保存一些系统会调用的特定函数.

驱动对象就类似于一个类对象,这个类对象直接被操作系统内核框架所操作,当一个驱动对象要加载时,系统会调用DriverEntry函数来构造此对象,函数的第一个参数就是DRIVER_OBJECT*,结构体指针,这个结构体指针就类似于this指针(C语言没有this指针,此处只是类比),在这个函数内,需要编写代码来初始化驱动对象的一些必要字段

  • PDRIVER_INITIALIZE DriverInit - 驱动对象初始化函数指针,此函数指针被I/O管理器初始化,指向DriverEntry函数

  • PDRIVER_STARTIO DriverStartIo - 驱动对象用于处理I/O的函数指针,此函数指针可以被设置为NULL

  • PDRIVER_UNLOAD DriverUnload - 驱动对象的卸载函数指针,当驱动被卸载时会被系统调用,此函数指针必须被赋值,否则当驱动被卸载时,字段为NULL会引发系统蓝屏

  • PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1] - 驱动对象的派遣函数指针数组. 这个数组中,不同的下标保存着不同的函数,下表列出了每个元素的下标(宏)所保存的函数指针,(这个数组内的函数指针都可以设置为NULL):

名称
调用时机
触发调用的API

IRP_MJ_CLEANUP
当本驱动对象的设备对象句柄被关闭(且引用计数为0),此函数会被调用. 但仍有I/O请求未被完成,可以在此函数中清理未完成的I/O请求.
CloseHandle

IRP_MJ_CLOSE
当本驱动对象的设备对象句柄被关闭(且引用计数为0),并且I/O请求已经被完成或已经全部取消,此函数会被调用. 此函数相当于设备对象的析构函数
CloseHandle

IRP_MJ_CREATE
当本驱动对象的设备对象被打开(通过CreateFile/ZwCreateFile),此函数会被调用. 此函数相当于设备对象的构造函数
CreateFile

IRP_MJ_DEVICE_CONTROL
设备控制,用于读/写设备对象
DeviceIoControl

IRP_MJ_FILE_SYSTEM_CONTROL

IRP_MJ_FLUSH_BUFFERS
写输出缓冲区或者丢弃输入缓冲区
FlushFileBuffers

IRP_MJ_INTERNAL_DEVICE_CONTROL

IRP_MJ_PNP

IRP_MJ_POWER
电源管理器发出的的请求

IRP_MJ_QUERY_INFORMATION
获取设备对象的长度
GetFileSize

IRP_MJ_READ
读取设备对象的内容
ReadFile

IRP_MJ_SET_INFORMATION
设置设备对象的长度

IRP_MJ_SHUTDOWN

IRP_MJ_SYSTEM_CONTROL

IRP_MJ_WRITE
将数据写到设备对象
WriteFile

这些函数都是可选的,当用户层或内核层通过设备的符号链接操作设备(打开,读,写,关闭)时,这些函数就会被调用.

也就是说,以前所使用的用户层API : CreateFile,GetFileSize,ReadFile,WriteFile,CloseHandle这些API操作的是一个设备对象,在内核中,文件属于一个设备对象.

同一个函数,能够操作不同的对象,这就是内核中通过C语言实现的多态了.

设备对象

设备对象一般是由驱动对象出来的(非即插即用驱动) . 驱动对象能够保存各种派遣函数,但是,这些派遣函数的一般是由I/O管理器所调用. 在调用派遣函数时,I/O管理器会将附加的信息打包到一个结构体,并传递给派遣函数. 一般这个结构体被称为IRP结构. 而只有设备对象才能接收到I/O管理器的I/O请求(什么是I/O请求? 比如,当一个文件的设备对象被打开(CreateFile)之后,对此文件的设备对象的读(ReadFile)和写(WriteFile)就是I/O请求) .

但是设备对象是不能独立存在的,设备对象能够接收I/O请求,但是却没有处理I/O请求的派遣函数,处理I/O请求的派遣函数保存在驱动对象中.

因此,在一个驱动项目中,要有两种对象存在:

  1. 驱动对象,能够保存处理I/O请求的派遣函数.

  2. 设备对象,能够接收到I/O请求.

而且,驱动对象无法被用户层代码所访问到,但是设备对象可以.

设备对象虽然在内核层,但是创建了DOS下的符号链接之后,在用户层中就可以通过CreateFile来打开设备对象. 并能够通过ReadFile,DeviceIOControl,GetFileSize等函数来间接地调用保存在驱动对象中的派遣函数. 它们的关系如下图所属:

04内核-驱动对象

设备对象的创建和销毁

  • IoCreateDevice - 创建设备对象

  • IoDeleteDevice - 销毁设备对象

符号链接

符号链接就是一个名字,DosDevicesD:这是一个盘符,但其实也可以视为一个符号链接名.它的作用是能够让用处层的API发出IO请求,并能够在发出IO请求时指定一个设备来处理此IO请求:

当用户层的应用程序发出一个IO请求时,对象管理器通过此符号链接名称来找到对应的设备,对象管理器能够解析符号链接的名称,以确定IO请求的目的地.

符号链接是给设备对象使用的,设备对象默认没有符号链接,没有符号链接的设备对象无法被用户层的代码所使用. 为设备对象创建符号链接之后才可以.

在内核中,符号链接的种类有两种:

  • (编辑:应用网_丽江站长网)

    【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读