Запись последних N байтов в файл, открытый с помощью FILE_FLAG_NO_BUFFERING - PullRequest
0 голосов
/ 05 марта 2020

При записи большого количества последовательных данных на диск я обнаружил, что при наличии внутреннего буфера 4 МБ и при открытии файла для записи я указываю [FILE_FLAG_NO_BUFFERING][1], так что используется мой внутренний буфер.

Но это также создает требование записи в полных секторальных блоках (512 байт на моем компьютере).

Как записать последние N <512 байт на диск? </p>

Есть ли какой-либо флаг в WriteFile, чтобы разрешить это ?

Можно ли дополнить их дополнительными NUL символами, а затем обрезать размер файла до правильного значения? (С SetFileValidData или подобным?)

Для тех, кому интересно, почему стоит попробовать этот подход. Наше приложение регистрирует много . Для этого существует специальный поток журналов, который форматирует и записывает журналы на диск. Также, если мы регистрируем с максимальной детализацией, мы можем регистрировать больше в секунду, чем может обработать дисковая система. (Обычно замечается для клиентов с системами SAN, которые не очень хорошо настроены.)

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

1 Ответ

0 голосов
/ 21 апреля 2020

Как отмечается в комментариях, запись файла таким образом, вероятно, не лучшее решение для реальных ситуаций. Но если используется запись с FILE_FLAG_NO_BUFFERING,
SetFileInformationByHandle - это способ пометить файл короче целых блоков.

int data_len = len(str);
int len_last_block = BLOCKSIZE%datalen;
int padding_to_fill_block = (data_last_block == BLOCKSIZE ? 0 : (BLOCKSIZE-len_last_block);
str.append('\0', padding_to_fill_block);

ULONG bytes_written = 0;
::WriteFile(hFile, data, data_len+padding_to_fill_block, &bytes_written, NULL));
m_filesize += bytes_written;;

LARGE_INTEGER end_of_file_pos;
end_of_file_pos.QuadPart = m_filesize - padding_to_fill_block;
if (!::SetFileInformationByHandle(hFile, FileEndOfFileInfo, &end_of_file_pos, sizeof(end_of_file_pos)))
{
    HRESULT hr = ::GetLastErrorMessage();
}
...