IOCP ReadFile всегда блокируется до завершения чтения

Если вы размещаете свое приложение-ответ на IIS, просто добавьте файл web.config, содержащий:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <httpErrors errorMode="Custom" existingResponse="Replace">
        <remove statusCode="404" subStatusCode="-1" />
        <error statusCode="404" path="/" responseMode="ExecuteURL" />
    </httpErrors>
  </system.webServer>
</configuration>

. Это скажет серверу IIS, чтобы вернуть основную страницу клиенту вместо ошибки 404 и нет необходимости использовать историю хэша.

0
задан webnoon 16 January 2019 в 11:56
поделиться

1 ответ

Прежде всего, IOCP здесь абсолютно не связаны. Вы пытаетесь проверить, являются ли операции ввода-вывода (читаются в вашем случае) на дескрипторе асинхронного дескриптора файла немедленным или блокированным. как здесь связан iocp ? Привязать iocp к файлу - это единственный способ получить уведомление, когда ввод-вывод завершен. но это абсолютно не влияет на сам блок ввода / вывода или немедленный возврат. мы можем использовать любой способ уведомления здесь. (APC, IOCP или событие). для вашего теста наиболее просто использовать событие.

тогда давайте посмотрим, как - как вы тестируете - читается блок или возвращается в ваш код? Вы не проверяете это вообще. проверьте эту потребность после возврата ReadFile - операция завершена или нет. операция ввода / вывода (ReadFile) завершается асинхронно - если вызов API уже возвращает вам управление, но OVERLAPPED (IO_STATUS_BLOCK) еще не обновлен системой, что означает, что ввод / вывод еще не завершен. OVERLAPPED обновлены, мы можем проверить прямой (Internal член структуры OVERLAPPED является не STATUS_PENDING) или по вызову GetOverlappedResult с bWait [ 1127] установлен в FALSE

Если этот параметр равен FALSE и операция еще не завершена, функция возвращает FALSE, а функция GetLastError возвращает ERROR_IO_INCOMPLETE .

, поэтому мы можем сказать, что ReadFile завершено асинхронно, если следующие 4 кодировки верны:

  1. ReadFile return FALSE
  2. GetLastError() return ERROR_IO_PENDING
  3. GetOverlappedResult(.., FALSE) return FALSE
  4. GetLastError() return ERROR_IO_INCOMPLETE

Вы не проверяете это в собственном коде. вместо этого вы ждете, пока операция io полностью не завершится через GetOverlappedResult(.., true), и занимает некоторое время. и какой смысл это делать?

реальный код для теста:

void tt(PCWSTR FileName)
{
    HANDLE hFile = CreateFile(FileName, FILE_GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
    if (hFile != INVALID_HANDLE_VALUE)
    {
        OVERLAPPED ov {};
        if (ov.hEvent = CreateEvent(0, 0, 0, 0))
        {
            char buf[1024];
            if (ReadFile(hFile, buf, sizeof(buf), 0, &ov))
            {
                DbgPrint("sync(#1)\n");
            }
            else
            {
                switch (GetLastError())
                {
                case ERROR_IO_PENDING:
                    ULONG n;
                    if (GetOverlappedResult(hFile, &ov, &n, FALSE))
                    {
                        DbgPrint("sync(#2)\n");
                    }
                    else 
                    {
                        switch (GetLastError())
                        {
                        case ERROR_IO_INCOMPLETE:
                            DbgPrint("async\n");
                            if (!GetOverlappedResult(hFile, &ov, &n, TRUE))
                            {
                                __debugbreak();
                            }
                            break;
                        default: __debugbreak();
                        }
                    }
                    break;
                default: __debugbreak();
                }
            }
            CloseHandle(ov.hEvent);
        }
        CloseHandle(hFile);
    }
}

обратите внимание, что результат (синхронный или нет) завершенного чтения зависит от того, являются ли данные файла в кеше. если вы вызываете его для файла, который не был прочитан ранее (то есть данные не в кеше), возможно, API выдает «async», но если вы снова вызовете эту функцию для того же файла - вы в следующий раз быстрее всех (почти на 100%) просмотр "sync (# 2)"

0
ответ дан RbMm 16 January 2019 в 11:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: