Самый быстрый способ получить часть файла на диске в определенный (предварительно выделенный) адрес памяти Windows/С++?

Как.

Я работаю в родной винде. Тем не менее, я хочу написать функцию, прототип которой выглядит примерно так:

void getData(uint8_t* p, std::string const& fn, size_t off, 
    size_t s, boost::function<void()> const& F);

Итак, у меня есть кусок памяти, предварительно выделенный в куче (с новым). У меня есть файл на диске. Я хотел бы указать указатель на свой кусок памяти ("p"), имя файла ("fn") и смещение в нем ("off"), размер ("s") и обратный вызов ("F") . Я бы хотел, чтобы подпрограмма в конечном итоге вызывала «F», когда моя память «p» была заполнена байтами «s» из файла «fn» со смещением «off». Я гарантирую, что «p», «s» и «off» выровнены с некоторой предопределенной степенью числа 2, но я бы не хотел, чтобы происходило копирование, которого можно было бы избежать. В идеале, данные с диска будут передаваться напрямую в мое местоположение.

Я изучил отображение файла в памяти, но для этого потребуется скопировать данные из отображаемой области в мой «p». Нет ли более быстрого способа сделать это?


person gavwould    schedule 03.12.2010    source источник
comment
Я бы использовал лучшие имена параметров, чем p, fn, s и F!   -  person John Warlow    schedule 03.12.2010
comment
Хм... вся цель отображаемых в память файлов состоит не в том, чтобы что-то копировать, а скорее в сопоставлении. Возможно, вам стоит разобраться в этом поглубже. Это очень мощная функция Windows, доступная с самой первой версии Windows NT.   -  person Simon Mourier    schedule 03.12.2010
comment
@ Саймон: зависит. Иногда вам нужно разобрать/переформатировать данные, чтобы работать с ними. Ммаппинг плюс копирование будут по-прежнему намного быстрее, чем обычный доступ к большим файлам.   -  person Konrad Rudolph    schedule 03.12.2010
comment
@Konrad: да, понимаешь, что ты имеешь в виду. Я имел в виду функцию getData выше, где я вижу, что файлы карты памяти идеально подходят :)   -  person Simon Mourier    schedule 03.12.2010
comment
@Simon: мне не нужно переформатировать или анализировать данные. Если я mmap + memcpy, Windows неизбежно будет передавать файл на диске в ОЗУ (как только во время memcpy произойдет сбой страницы, если не раньше), а затем memcpy скопирует эти байты в мой кусок памяти ('p'). Я не хочу делать больше работы (т.е. копировать), чем необходимо; поэтому вопрос можно перефразировать так: действительно ли это самый быстрый способ получить большой файл с диска в мою предварительно выделенную память?   -  person gavwould    schedule 27.12.2010
comment
@ user321091 - Я думаю, MMF подойдет, если вы также хотите скопировать байты. Однако вы только что добавили одну очень важную информацию к своему вопросу. Вы сказали большой файл. Теперь история действительно может быть другой. Это зависит от того, насколько велика машина (RAM, 32/64-бит и т. д.). См. эту ссылку для обсуждения больших MMF: блоги. msdn.com/b/khen1234/archive/2006/01/30/519483.aspx (и комментарии тоже стоит прочитать)   -  person Simon Mourier    schedule 27.12.2010


Ответы (1)


Почему бы просто не использовать сопоставление памяти с MapViewOfFileEx?

Вы можете использовать p в качестве параметра lpBaseAddress для отображения файла в любом месте адресного пространства вашего процесса.

person JoeG    schedule 03.12.2010
comment
В яблочко. Плюс я бы добавил, что boost::signal не соответствует самому быстрому способу. На самом деле это ужасно с точки зрения производительности - person valdo; 03.12.2010
comment
Я не думаю, что это сработает. Из документации: Никакое другое выделение памяти не может происходить в регионе, который используется для маппинга, включая использование функции VirtualAlloc или VirtualAllocEx для резервирования памяти. Я только что проверил это, и MapViewOfFileEx() не работает с ошибкой ERROR_INVALID_ADDRESS. Если вы освободите память, а затем попытаетесь отобразить ее снова, у вас все получится. - person Luke; 03.12.2010
comment
@ Люк: Действительно. Указатель — это подсказка; больше ничего. В моем случае он, очевидно, уже выделен, поэтому Windows не может его отобразить. - person gavwould; 27.12.2010