驱动读写超时处理

关于驱动读写异步超时的处理,网络上的资料相对稀少,正好最近在工作上遇到了这个问题,所以就研究了一下,发现还是有些门道的。如果完全按照应用层读写超时的处理逻辑来处理驱动层的话就会出现蓝屏等问题

只要涉及到读写超时,那么我们第一印象肯定会想到事件和事件等待相关操作与函数的调用,那么我们来看一下驱动的几个文件操作函数声明:

首先是打开操作

NTSTATUS ZwCreateFile(
  _Out_    PHANDLE            FileHandle,
  _In_     ACCESS_MASK        DesiredAccess,
  _In_     POBJECT_ATTRIBUTES ObjectAttributes,
  _Out_    PIO_STATUS_BLOCK   IoStatusBlock,
  _In_opt_ PLARGE_INTEGER     AllocationSize,
  _In_     ULONG              FileAttributes,
  _In_     ULONG              ShareAccess,
  _In_     ULONG              CreateDisposition,
  _In_     ULONG              CreateOptions,
  _In_opt_ PVOID              EaBuffer,
  _In_     ULONG              EaLength
);

根据应用层的经验,如果要实现超时读写,我们需要以异步的方式打开文件,而驱动默认即是异步打开操作,如果你需要同步打开,需要设置下面的值(两个需要同时设置)
DesiredAccess:SYNCHRONIZE
CreateOptions:FILE_SYNCHRONOUS_IO_NONALERT

然后是读写函数,两个类似

NTSTATUS ZwReadFile(
  _In_     HANDLE           FileHandle,
  _In_opt_ HANDLE           Event,
  _In_opt_ PIO_APC_ROUTINE  ApcRoutine,
  _In_opt_ PVOID            ApcContext,
  _Out_    PIO_STATUS_BLOCK IoStatusBlock,
  _Out_    PVOID            Buffer,
  _In_     ULONG            Length,
  _In_opt_ PLARGE_INTEGER   ByteOffset,
  _In_opt_ PULONG           Key
);

NTSTATUS ZwWriteFile(
  _In_     HANDLE           FileHandle,
  _In_opt_ HANDLE           Event,
  _In_opt_ PIO_APC_ROUTINE  ApcRoutine,
  _In_opt_ PVOID            ApcContext,
  _Out_    PIO_STATUS_BLOCK IoStatusBlock,
  _In_     PVOID            Buffer,
  _In_     ULONG            Length,
  _In_opt_ PLARGE_INTEGER   ByteOffset,
  _In_opt_ PULONG           Key
);

这里根据应用层的经验,我们会找关于事件(Event)的参数,根据文档声明,正好第二个参数涉及到了事件,查阅文档后确定该参数可以用于异步超时等待。这个时候我们需要创建一个事件,关于驱动中创建事件的函数我们首先会想到 KeInitializeEvent ,但是此处需要的是 HANDLE 类型,所以我们需要使用下面的方法来创建:

ZwCreateEvent(&g_hEvent, GENERIC_ALL, NULL, SynchronizationEvent, FALSE);

然后我们自然想到以Zw开头来搜索相关的等待函数

status = ZwWaitForSingleObject(g_hEvent, FALSE, &time);

这个时候如果status返回的是 STATUS_TIMEOUT ,那么就代表文件读写超时,这时候我们就关闭事件句柄和文件句柄然后返回。如果你真的这么做了,那么等数据真正的返回的时候,就会出现蓝屏问题。

经过分析发现是因为我们在使用 ZwClose 函数关闭句柄后,windows并没有停止对文件的操作,由于是是异步的,所以后台仍然在等待数据的返回,如果这时候我们销毁了资源,但是数据在超时后返回,那么就会出现 0xc0000005 这种内存访问错误蓝屏。那么我们理所当然想到是否有一个函数用来取消文件IO操作,答案是有的,但是是未文档化函数,函数声明如下:

typedef
NTSTATUS
(NTAPI *MyZwCancelIoFile)(
    IN HANDLE               FileHandle,
    OUT PIO_STATUS_BLOCK    IoStatusBlock);

这个函数即可用来取消文件IO,当我们读写超时后,我们先要取消文件后台IO操作,然后再关闭相关句柄。我们可以这样获得该函数地址:

UNICODE_STRING funcname = RTL_CONSTANT_STRING(L"ZwCancelIoFile");
ZwCancelIoFile = (MyZwCancelIoFile)MmGetSystemRoutineAddress(&funcname);
if (ZwCancelIoFile == NULL)
{
    return FALSE;
}

~完毕~

原文地址:https://www.cnblogs.com/magicdmer/p/10994140.html

时间: 2024-11-14 12:35:35

驱动读写超时处理的相关文章

驱动读写进程内存R3,R0通信

1 stdafx.h 头文件代码 2 3 #ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later. 4 #define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows. 5 #endif 6 7 #ifdef __cplusplus 8 extern "C

Smart210学习记录-----SD/MMC/SDIO驱动

转自:http://jingpin.jikexueyuan.com/article/23369.html 一.SD/MMC/SDIO概念区分 SD(SecureDigital)与 MMC(MultimediaCard) SD 是一种 flash memory card 的标准,也就是一般常见的 SD 记忆卡,而 MMC 则是较早的一种记忆卡标准,目前已经被 SD 标准所取代.在维基百科上有相当详细的 SD/MMC 规格说明:[http://zh.wikipedia.org/wiki/Secure

Linux SD/MMC/SDIO驱动分析

一.SD/MMC/SDIO概念区分 SD(SecureDigital)与 MMC(MultimediaCard) SD 是一种 flash memory card 的标准,也就是一般常见的 SD 记忆卡,而 MMC 则是较早的一种记忆卡标准,目前已经被 SD 标准所取代.在维基百科上有相当详细的 SD/MMC 规格说明:[http://zh.wikipedia.org/wiki/Secure_Digital]. SDIO(SecureDigital I/O) SDIO 是目前我们比较关心的技术,

Linux SD/MMC/SDIO驱动分析_转

转自:Linux SD/MMC/SDIO驱动分析    https://www.cnblogs.com/cslunatic/p/3678045.html#3053341 一.SD/MMC/SDIO概念区分 SD(SecureDigital)与 MMC(MultimediaCard) SD 是一种 flash memory card 的标准,也就是一般常见的 SD 记忆卡,而 MMC 则是较早的一种记忆卡标准,目前已经被 SD 标准所取代.在维基百科上有相当详细的 SD/MMC 规格说明:[htt

JAVA Socket超时浅析(转)

套接字或插座(socket)是一种软件形式的抽象,用于表达两台机器间一个连接的“终端”.针对一个特定的连接,每台机器上都有一个“套接字”,可以想象它们之间有一条虚拟的“线缆”.JAVA有两个基于数据流的套接字类:ServerSocket,服务器用它“侦听”进入的连接:Socket,客户端用它初始一次连接.侦听套接字只能接收新的连接请求,不能接收实际的数据包. 套接字是基于TCP/IP实现的,它是用来提供一个访问TCP的服务接口,或者说套接字socket是TCP的应用编程接口API,通过它应用层就

WebClient的超时问题及解决

WebClient的超时问题及解决 转自:http://blog.163.com/[email protected]/blog/static/62440288201112245345838/ Webclient在下载请求时无法设置请求超时时间和请求读写超时时间.WebClient在异步下载时遇到网络不通等问题时没有响应超时造成app挂起. 1.Webclient请求超时设置      重写Webclient的GetWebRequest方法,为HttpWebRequest添加请求超时及读写超时  

PHP超时处理全面总结

后端接口访问超时 HTTP访问 一般我们访问HTTP方式很多,主要是:curl, socket, file_get_contents() 等方法. 如果碰到对方服务器一直没有响应的时候,我们就悲剧了,很容易把整个服务器搞死,所以在访问http的时候 后端&接口访问超时HTTP访问 一般我们访问HTTP方式很多,主要是:curl, socket, file_get_contents() 等方法. 如果碰到对方服务器一直没有响应的时候,我们就悲剧了,很容易把整个服务器搞死,所以在访问http的时候也

Linux的fasync驱动异步通知详解

工作项目用有个需求是监测某个GPIO输入方波的频率!通俗的讲就是一个最最简单的测方波频率的示波器!不过只是测方波的频率!频率范围是0~200HZ,而且频率方波不是一直都是200HZ,大多数的时候可能一直是0或者一个更低频率的方波!同时要考虑到方波有可能一直维持在200HZ ,同时保持效率和性能的情况下,fasync驱动异步通知是个不错的选择,当初写demo的时候实测1K的方波完全没有问题!应用到项目中也是完全能满足需求!驱动很简单!业余时间把自己之前学到的知识总结一下!对自己也是个提高! 根据需

PHP超时处理全面总结(转)

[ 概述 ] 在PHP开发中工作里非常多使用到超时处理到超时的场合,我说几个场景: 1. 异步获取数据如果某个后端数据源获取不成功则跳过,不影响整个页面展现 2. 为了保证Web服务器不会因为当个页面处理性能差而导致无法访问其他页面,则会对某些页面操作设置 3. 对于某些上传或者不确定处理时间的场合,则需要对整个流程中所有超时设置为无限,否则任何一个环节设置不当,都会导致莫名执行中断 4. 多个后端模块(MySQL.Memcached.HTTP接口),为了防止单个接口性能太差,导致整个前面获取数