Эта программа работает асинхронно или синхронно? - PullRequest
4 голосов
/ 06 мая 2009

Когда я запускаю эту программу

OVERLAPPED o;

int main()
{
    ..
    CreateIoCompletionPort(....);

    for (int i = 0; i<10; i++)
    {
        WriteFile(..,&o);

        OVERLAPPED* po;
        GetQueuedCompletionStatus(..,&po);
    }
}

похоже, что WriteFile не возвращался до тех пор, пока не была завершена работа по записи. В то же время вызывается GetQueuedCompletionStatus (). Поведение похоже на операцию синхронного ввода-вывода, а не на операцию асинхронного ввода-вывода.

Почему это?

Ответы [ 4 ]

2 голосов
/ 06 мая 2009

Если для дескриптора файла и тома включено кэширование записи, операция с файлом может завершиться с копией памяти в кэш, которая будет отложена позже. Поскольку фактического ввода-вывода не происходит, в этом случае нет причин выполнять асинхронный ввод-вывод.

Внутренне каждая операция ввода-вывода представлена ​​ IRP (пакет запроса ввода-вывода). Он создается ядром и передается файловой системе для обработки запроса, где он проходит через многоуровневые драйверы, пока запрос не станет действительной командой контроллера диска. Этот драйвер сделает запрос, пометит IRP как ожидающий и вернет управление потоком. Если дескриптор был открыт для перекрывающегося ввода-вывода, ядро ​​немедленно возвращает управление вашей программе. В противном случае ядро ​​будет ожидать завершения IRP, прежде чем вернуться.

Однако не все операции ввода-вывода проходят на диск. Файловая система может определить, что запись должна быть кэширована, а не записана позднее. Существует даже специальный путь для операций, который может быть полностью выполнен с использованием кэша, называемый fast IO . Даже если вы делаете асинхронный запрос, быстрый ввод-вывод всегда является синхронным, поскольку он просто копирует данные в кэш и из него.

Монитор процесса в расширенном режиме вывода отображает различные режимы и будет отображаться пустым в поле состояния во время ожидания IRP.

Существует ограничение на количество данных, которые могут быть сохранены в кэше записи. После заполнения операции записи не будут завершены немедленно. Попробуйте записать много данных одновременно с майскими операциями.

1 голос
/ 07 мая 2009

Я написал блог, который некоторое время назад опубликовал статью «Когда асинхронные файлы записывают не асинхронно», и, к сожалению, ответ был «большую часть времени». Смотрите сообщение здесь: http://www.lenholgate.com/blog/2008/02/when-are-asynchronous-file-writes-not-asynchronous.html

Суть этого:

  • В целях безопасности Windows расширяет файлы синхронно
  • Вы можете попытаться обойти эту проблему, установив в конце файла большое значение перед началом, а затем обрезав файл до нужного размера, когда закончите.
  • Вы можете указать менеджеру кэша использовать ваши буферы, а не его, используя FILE_FLAG_NO_BUFFERING
  • По крайней мере, это не так плохо, как будто вы вынуждены использовать FILE_FLAG_WRITE_THROUGH
0 голосов
/ 06 мая 2009

из этой страницы в MSDN:

Для асинхронных операций записи, hFile может быть любой ручкой, открытой функция CreateFile, использующая FILE_ FLAG_OVERLAPPED флаг или сокет дескриптор, возвращаемый сокетом или принять функцию.

также с этой страницы :

Если указана ручка, она должна были открыты для перекрытия ввода / вывода завершение. Например, вы должны укажите флаг FILE_FLAG_OVERLAPPED при использовании функции CreateFile для получить ручку.

0 голосов
/ 06 мая 2009

Если вызывается GetQueuedCompletionStatus, то вызов WriteFile является синхронным (и он вернулся), но он все равно может изменить & o даже после того, как он будет возвращен, если он асинхронный.

...