<windows内核编程>谭文--第九章<虚拟磁盘>笔记 这是我看书大概看到结尾后的复习篇笔记.
参考源码:Ramdisk---github的地址是:github.com/guidoreina/… 基于WDF的驱动框架,功能是实现一个虚拟磁盘,将内存容量当成磁盘容量来用.
WDF和WDM之间的差异: 微软给出的官方文档解释是 1.对象上下文.如WDM中的DeviceObject->Extension,在WDF中被称作对象上下文区域.等效于WDM的设备扩展. 2.设备支持的IRP.对WDM接受到的IRP进行了封装,在WDF中变成了一个个的回调函数. 3.WDF创建一个WDF队列. 4.同步处理.在WDM中涉及到同步/并发的时候经常要用到锁/事件.但WDF中并不会用到那么多的锁/事件,大意是因为WDF框架在每个回调函数中已经加入了. 总结:WDF与WDM之间的关系在我看来很像是C与C++的关系,WDF是WDM的子集,用WDF可以做到的事情,用WDM也可以,但是肯定不如WDF在某些任务上方便快捷.
在编写驱动开始代码之前,考虑设备扩展需要什么数据. EVT_WDF_DRIVER_DEVICE_ADD 函数是初始化一个虚拟磁盘,磁盘需要参数,比如磁盘大小,磁盘开始地址,磁盘类型,以及一个DISK_GEOMETRY类型.类型见下文.这里用到的是DISK_GEOMETRY,虽然微软不推荐使用,但是源码作者是这么做的,回头我再修改. 一些WDF特色IRP回调函数: EVT_WDF_DRIVER_DEVICE_ADD EvtDriverDeviceAdd; EVT_WDF_DEVICE_CONTEXT_CLEANUP EvtCleanuoCallback;
EVT_WDF_IO_QUEUE_IO_READ EvtIoRead; EVT_WDF_IO_QUEUE_IO_WRITE EvtIoWrite; EVT_WDF_IO_QUEUE_IO_DEVICE_CONTROL EvtIoDeviceControl;
主要需要关注的函数有 EvtDriverDeviceAdd/EvtIoRead/EvtIoWrite/EvtIoDeviceControl/ EvtDriverDeviceAdd:相当于WDM中驱动的AddDevice函数. EvtIoRead:相当于WDM中接收到IRP_MJ_READ的分发函数. EvtIoWrite:同理. EVtIoDeviceControl:同理.
EvtDriverDeviceAdd:要做的是有,新建设备,从注册表中拿到配置 EvtIoRead:把请求的缓冲区数据存到虚拟磁盘的空间中. EvtIoWrite:同理. EvtIoDeviceControl:主要处理系统发来的IOCTL,比如IOCTL_DISK_GET_PARTITION_INFO...
EvtDriverDeviceAdd:这个函数,解析一下步骤,用PWDFDEVICE_INIT device_init,这个参数,来做到初始化设备功能,给虚拟磁盘分配内存,初始化队列,队列回调函数赋值,对象命名. EvtCleanupCallback:这个函数作为对象引用计数为0时调用,也就是说我们的WDFDEVICE在引用计数为0时,会调用这个回调,所以要释放我们分配的内存. EvtIoRead:通过WDFREQUST requst这个参数获取到WDF_REQUEST_PARAMETERS parameters,parameters使用前需要先初始化,WDF_REQUEST_PARAMETERS_INIT(¶meters),然后复制内存到缓冲区,WdfMemoryCopyToBuffer. EVtIoWrite:同理. EvtIoDeviceControl:主要负责系统的请求.比如IOCTL_DISK_GET_PARTITION_INFO/IOCTL_DISK_SET_PARITION_INFO.
tips:这个项目没有多少代码,逻辑比较简单,我本来打算是把这个ramdisk中的数据结构从替换成微软建议使用的新的数据结构,比如说是DISK_GEOMETRY到DISK_GEOMETRY_EX,但是我失败了,代码在这里github:github.com/likecarrot?… 这个项目用到的东西真的不多,但是对于系统的了解恐怕是我失败的主要原因.
数据类型参考:
typedef struct _DISK_GEOMETRY { LARGE_INTEGER Cylinders; MEDIA_TYPE MediaType; ULONG TracksPerCylinder; ULONG SectorsPerTrack; ULONG BytesPerSector; } DISK_GEOMETRY, *PDISK_GEOMETRY; //微软提示这个数据结构已经过时,新驱动必须使用DISK_GEOMETRY_EX.新结构如下: typedef struct _DISK_GEOMETRY_EX { DISK_GEOMETRY Geometry; LARGE_INTEGER DiskSize; UCHAR Data[1]; } DISK_GEOMETRY_EX, *PDISK_GEOMETRY_EX; Geometry:同上文. DiskSize:磁盘大小. Data:数据块的开头,从一个DISK_PARTITION_INFO后跟一个DISK_DETECTION_INFO结构. typedef struct _DISK_PARTITION_INFO { ULONG SizeOfPartitionInfo; PARTITION_STYLE PartitionStyle; union { struct { ULONG Signature; ULONG CheckSum; } Mbr; struct { GUID DiskId; } Gpt; } DUMMYUNIONNAME; } DISK_PARTITION_INFO, *PDISK_PARTITION_INFO; SizeOfPartitionInfo:此结构的大小. PartitionStyle:指定磁盘包含的分区表的类型,使用PARTITION_STYLE的枚举. typedef enum _PARTITION_STYLE { PARTITION_STYLE_MBR = 0, PARTITION_STYLE_GPT = 1, PARTITION_STYLE_RAW = 2 } PARTITION_STYLE; PARTITION_STYLE_MBR:指定传统的AT样式的主引导记录,分区表的类型. PARTITION_STYLE_GPT:指定分区表的GUID分区表类型. PARTITION_STYLE_RAW:无解释. DUMMYUNIONNAME:union,基于PartitionStyle的值决定. typedef struct _DISK_DETECTION_INFO { ULONG SizeOfDetectInfo; DETECTION_TYPE DetectionType; union { struct { DISK_INT13_INFO Int13; DISK_EX_INT13_INFO ExInt13; } DUMMYSTRUCTNAME; } DUMMYUNIONNAME; } DISK_DETECTION_INFO, *PDISK_DETECTION_INFO; SizeOfDetectInfo:包含检索到的检测信息的数量(以字节为单位). DetectionType:指示以下三种可能的检测类型之一:DetectNone,DetectInt13,DetectExInt13. DetectNone:指示磁盘既不包含INT13h分区,也不包含扩展的INT13h分区. DetectInt13:指示磁盘具有标准的INT13h分区. DetectExInt13:指示磁盘包含扩展的INT13h分区.
Remarks:DISK_GEOMETRY_EX必须配合IOCTL_DISK_GET_DRIVE_GEOMETRY_EX和IOCTL_DISK_GET_MEDIA_TYPES使用. //可以看到两个结构是差不多的,之前考虑的设备上下文中提到的磁盘大小,磁盘开始地址,在EX结构中都有.