Как асинхронно вызвать код DeviceIOControl?

Я пытаюсь асинхронно вызывать функции DeviceIO, используя структуру OVERLAPPED, как описано в MSDN. Я использую управляющий код FSCTL_ENUM_USN_DATA для перечисления MFT дисков NTFS, но не могу запустить его асинхронно. Дескриптор файла создается с FILE_FLAG_OVERLAPPED, но нет никакой разницы, использую ли я перекрывающуюся структуру с FILE_FLAG_OVERLAPPED или нет. Функция не возвращается сразу. Кажется, что это синхронно в обоих случаях. В приведенном ниже примере показано перечисление первых 100 000 записей MFT на диске C:\. Поскольку я не так хорошо знаком с использованием перекрывающихся структур, возможно, я сделал что-то не так. Мой вопрос: Как я могу выполнить DeviceIoControl(hDevice, FSCTL_ENUM_USN_DATA,...) асинхронно? Спасибо за любую помощь.

#include "stdafx.h"
#include <Windows.h>

typedef struct {
  DWORDLONG  nextusn;
  USN_RECORD FirstUsnRecord;
  BYTE Buffer[500];
}TDeviceIoControlOutputBuffer, *PTDeviceIoControlOutputBuffer;

int _tmain(int argc, _TCHAR* argv[])
{
    MFT_ENUM_DATA lInputMftData;
    lInputMftData.StartFileReferenceNumber = 0;
    lInputMftData.MinMajorVersion = 2;
    lInputMftData.MaxMajorVersion = 3;
    lInputMftData.LowUsn = 0;
    lInputMftData.HighUsn = 0;

    TDeviceIoControlOutputBuffer lOutputMftData;
    DWORD lOutBytesReturned = 0;
    HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    OVERLAPPED  lOverlapped = { 0 };
    lOverlapped.hEvent = hEvent;
    LPCWSTR path = L"\\\\.\\C:";
    HANDLE hDevice = CreateFile(path, GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
    if (hDevice != INVALID_HANDLE_VALUE) {
        lOutputMftData.nextusn = 0;
        while (lOutputMftData.nextusn < 100000) {
            lInputMftData.StartFileReferenceNumber = lOutputMftData.nextusn;
            BOOL result = DeviceIoControl(hDevice, FSCTL_ENUM_USN_DATA, &lInputMftData, sizeof(lInputMftData), &lOutputMftData, sizeof(lOutputMftData), &lOutBytesReturned, &lOverlapped);
        }
    }
}

person jampeter    schedule 08.07.2014    source источник
comment
Если драйвер не поддерживает асинхронный ввод-вывод вообще или для какого-либо запроса, он обрабатывает запрос ввода-вывода синхронно, игнорируя параметр OVERLAPPED. Однако я не знаю, поддерживает ли этот драйвер этот конкретный запрос в режиме асинхронного ввода-вывода.   -  person Alex F    schedule 08.07.2014
comment
Спасибо за ответ. Согласно Microsoft FSCTL_ENUM_USN_DATA можно назвать асинхронным: msdn.microsoft.com/en-us/library/windows/desktop/   -  person jampeter    schedule 08.07.2014
comment
Что ж, взглянув еще раз на ваш код, я не вижу, чтобы вы заполняли член hEvent переменной lOverlapped. Это может быть хорошей причиной для синхронного выполнения этого запроса.   -  person Alex F    schedule 08.07.2014


Ответы (2)


TL:DR — вы получаете асинхронное поведение только в том случае, если драйвер, получивший ваш запрос, ожидает его.

Когда вы вызываете DeviceIoControl и передаете перекрывающуюся структуру, это не гарантирует, что операция будет асинхронной. Это означает, что он может быть асинхронным. Это зависит от того, как реализован драйвер, который получит ваш запрос. Когда вы запускаете DeviceIoControl, он создает irp и отправляет его драйверу. DeviceIoControl переведет ваш поток в режим ядра, чтобы создать и отправить irp. Обратный вызов драйвера будет вызван в этом потоке для обработки запроса. Если драйвер решает обработать (и завершить) запрос немедленно, то запрос выполняется синхронно. В этом потоке нет никакой разницы между открытием драйвера с FILE_FLAG_OVERLAPPED или без него. Если драйвер решит отложить запрос, вы увидите настоящее асинхронное поведение. DeviceIoControl вернет FALSE, а GetLastError вернет ERROR_IO_PENDING. Это означает, что irp ожидает завершения, и о событии, указанном вами в структуре OVERLAPPED, будет сообщено, когда irp завершится.

person shaked cohen    schedule 28.01.2020

person    schedule
comment
Спасибо. Но все еще не работает. Нет асинхронности. Перекрывающаяся структура и дескриптор устройства должны быть правильными: если я позвоню, например. функция 'readfile' с той же перекрывающейся структурой и тем же дескриптором hdevice немедленно возвращается с GetalstError() = 997 (ERROR_IO_PENDING: выполняется операция перекрывающегося ввода-вывода), что указывает на то, что 'readfile' вызывается асинхронно. Но это не работает для устройства. - person jampeter; 10.07.2014