DeviceIoControl超时后如何处理

在使用 DeviceIoControl 函数时,如果发生超时并且你希望手动中断或取消正在进行的 I/O 操作,可以通过以下几种方式来处理:

1. 使用 CancelIo 函数

CancelIo 是 Windows API 提供的一个函数,用于取消指定设备句柄的所有挂起的异步 I/O 操作。它只会影响异步操作(即 OVERLAPPED 模式下的 I/O 请求)。

使用方法:

cpp 复制代码
BOOL result = CancelIo(hDevice);
if (!result) {
    DWORD dwError = GetLastError();
    // 处理错误
}

该函数会取消当前设备句柄上的所有未完成的异步 I/O 操作,包括 DeviceIoControl 请求。要注意:

  • 取消操作后,相关的 I/O 操作将不会完成,GetLastError() 会返回 ERROR_OPERATION_ABORTED
  • CancelIo 只能取消未完成的 I/O 请求,已经完成的请求无法取消。

2. 使用 CancelIoEx 函数

CancelIoExCancelIo 的增强版本,它允许指定取消特定线程或设备句柄的 I/O 请求。它也适用于异步模式。

使用方法:

cpp 复制代码
BOOL result = CancelIoEx(hDevice, NULL);
if (!result) {
    DWORD dwError = GetLastError();
    // 处理错误
}

CancelIoEx 允许通过指定 OVERLAPPED 结构来取消特定的异步 I/O 操作,或者传入 NULL 来取消所有挂起的操作。

3. 取消 OVERLAPPED 操作(异步模式)

如果你使用了 OVERLAPPED 结构,且正在等待某个异步 I/O 操作完成(例如使用 WaitForSingleObject 等等待 I/O 完成),你可以通过取消等待来停止操作。

cpp 复制代码
// 假设使用 OVERLAPPED 和 WaitForSingleObject
DWORD dwWaitResult = WaitForSingleObject(overlapped.hEvent, timeoutMilliseconds);
if (dwWaitResult == WAIT_TIMEOUT) {
    // 超时后取消 I/O 操作
    CancelIo(hDevice);  // 或者使用 CancelIoEx
}

在超时发生后,你可以使用 CancelIoCancelIoEx 来取消正在进行的异步操作。

4. 异步 I/O 中的错误处理

如果你使用的是异步 I/O(OVERLAPPED),当 DeviceIoControl 返回超时错误时,可以通过检查 GetLastError() 返回的错误代码来判断是否需要中断。

cpp 复制代码
if (GetLastError() == ERROR_OPERATION_ABORTED) {
    // 操作被中断,处理相关逻辑
}

5. 线程间通信中断

如果你在多线程环境中使用异步 I/O,且希望中断操作,可以通过线程间的信号机制(如 EventMutexCriticalSection 等)来控制。你可以在某个线程中设置一个标志或事件,然后在等待 I/O 完成的线程中定期检查该标志,如果标志被设置,就提前退出或中断操作。

示例代码:取消异步 I/O 操作

cpp 复制代码
#include <windows.h>
#include <iostream>

HANDLE hDevice;
OVERLAPPED overlapped = { 0 };
BOOL bResult;

// 超时后中断 I/O 操作
void CancelIoAfterTimeout()
{
    // 假设你已经设置了一个等待事件
    DWORD dwWaitResult = WaitForSingleObject(overlapped.hEvent, 5000);  // 设置 5 秒超时

    if (dwWaitResult == WAIT_TIMEOUT) {
        std::cout << "I/O operation timed out, canceling...\n";
        CancelIo(hDevice);  // 取消所有异步 I/O 操作
        // 或者使用 CancelIoEx(hDevice, &overlapped); 如果需要取消特定操作
    } else {
        std::cout << "I/O operation completed\n";
    }
}

int main()
{
    // 假设hDevice是已打开的设备句柄
    hDevice = CreateFile(L"\\\\.\\Device\\MyDevice", GENERIC_READ | GENERIC_WRITE,
                         0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    
    if (hDevice == INVALID_HANDLE_VALUE) {
        std::cerr << "Failed to open device: " << GetLastError() << "\n";
        return 1;
    }

    // 发起异步 I/O 操作
    bResult = DeviceIoControl(hDevice, IOCTL_CODE, NULL, 0, NULL, 0, NULL, &overlapped);
    if (!bResult) {
        if (GetLastError() == ERROR_IO_PENDING) {
            // 操作正在进行,等待超时
            CancelIoAfterTimeout();
        }
    }

    CloseHandle(hDevice);
    return 0;
}

注意事项:

  • 在取消操作后,通常需要检查设备的状态或驱动程序的返回值。取消操作后,可能会导致 DeviceIoControl 调用返回错误,例如 ERROR_OPERATION_ABORTED
  • 如果你不使用异步 I/O(即没有 OVERLAPPED 结构),则无法直接取消操作。在这种情况下,你可能需要使用线程或进程间的控制机制来中断操作。

希望这些方法能帮助你处理中断超时的 I/O 操作!

相关推荐
恒锐丰科技韩生22 分钟前
率能 SS6625E|3.0~20V 单通道 H 桥直流电机驱动 SOP8 电子锁玩具机器人分享
嵌入式硬件·硬件工程
zlinear数据采集卡27 分钟前
D223 ADC数据处理流水线:从原始采样值到工程单位的完整转换链
开发语言·arm开发·嵌入式硬件·fpga开发·开源·c#
Dr.kangder2 小时前
嵌入式面试总结(十八)——JTAG调试
嵌入式硬件·面试·职场和发展·架构·嵌入式
恒锐丰科技韩生2 小时前
率能 SS6226|2.4~7.2V 低压双通道双 H 桥电机驱动 SOP16 玩具小家电专用芯片
嵌入式硬件·硬件工程
WWJA王文举3 小时前
RS485通信超时全面排查:终端电阻、A/B线、DE方向控制、串口参数和Modbus一次讲透
stm32·通信协议·rs485
Dr.kangder4 小时前
嵌入式面试总结(十九)——内存泄露
单片机·算法·面试·职场和发展·架构·硬件架构
萌新小白YXY6 小时前
SAE J1587/SAE J1708 协议笔记
笔记·单片机·嵌入式硬件
恒锐丰科技韩生7 小时前
率能 SS6635E|3.0~30V 直流双向 H 桥电机驱动 SOP8 玩具电子锁机器人分享
嵌入式硬件·硬件工程
嘉子的秃头日记7 小时前
机械革命“自动修复”无法修复你的电脑
stm32·单片机·电脑
恒锐丰科技林技术员7 小时前
高集成双通道 H 桥驱动芯片 SS6850H:低压直流电机驱动优选方案
嵌入式硬件·硬件工程