Здравствуйте, Poseidon, Вы писали:
P>Здравствуйте! Не секрет что mapviewoffile терпит неудачу при работе с достаточно большим по размеру файлом. P>Вопрос — можно ли это вылечить если сначала вызвать CreateFileMapping или MapViewOfFile с флагом MEM_RESERVE?
Нет.
1. MapViewOfFile не может мапить в указанную память. MapViewOfFileEx может, но та память должна быть свободна, а не зарезервирована.
2. Неудача приманивания больших файлов может быть из-за отсутствия соответствующего непрерывного куска адресного пространства. Но к нехватке физической памяти это мало относится.
Что может помочь: использование x64 и сборка с /LARGEADDRESSAWARE. Тогда будет 8 TB адресного пространства, 128 TB начиная с Windows 8.1
Здравствуйте, Poseidon, Вы писали:
P>хотя файл не такой уж большой, чуть менее 1 ГБ P>на диске 19 ГБ свободно
P>можно ли заранее узнать какой объем можно безопасно маппить?
Можно, например, составить карту памяти через VirtualQuery, или попробовать VirtualAlloc и потом освободить.
Но ненадёжно: память может стать фрагментированной между проверкой и вызовом.
Я так понимаю, система 64-битное, приложение 32-битное?
1 ГБ это тот объём, для которого неудача примапить в обычное 32 битное приложение предсказуема — там всего 2 ГБ адресного пространства.
Простое включение /LARGEADDRESSAWARE увеличивает его до 4 ГБ:
Это увеличивает шансы на успех.
Перевод на x64 вместе со включенным /LARGEADDRESSAWARE даёт от 8 ТБ, ну то есть примапить 1 ГБ вообще не проблемой становится.
(Перевод на х64 без включения /LARGEADDRESSAWARE не даёт ничего)
Здравствуйте, Poseidon, Вы писали:
P>Здравствуйте! Не секрет что mapviewoffile терпит неудачу при работе с достаточно большим по размеру файлом. P>Вопрос — можно ли это вылечить если сначала вызвать CreateFileMapping или MapViewOfFile с флагом MEM_RESERVE? P>Для достаточно большой области памяти. P>А потом узнать объем памяти которую можно закомитить (кстати какой функцией это можно сделать?) P>Заключить код работы с памятью в SEH и при возникновении ошибки доступа к памяти вызывать MapViewOfFile P>повторно с указанием флага MEM_COMMIT и размера блока который система способна выделить?
P>делал нечто подобное с VirtualAlloc, а теперь хочу разобраться как это можно сделать для образа файла.
MEM_RESERVE обычно используется если память надо выделить по определенному адресу. Если адрес не имеет значение, можно просто MEM_COMMIT.
Если какие то есть проблемы с большими файлами (о чем я не знаю), можно просто маппить не весь файл, а его часть?
См. 3 последние аргумента MapViewOfFile.
Здравствуйте! Не секрет что mapviewoffile терпит неудачу при работе с достаточно большим по размеру файлом.
Вопрос — можно ли это вылечить если сначала вызвать CreateFileMapping или MapViewOfFile с флагом MEM_RESERVE?
Для достаточно большой области памяти.
А потом узнать объем памяти которую можно закомитить (кстати какой функцией это можно сделать?)
Заключить код работы с памятью в SEH и при возникновении ошибки доступа к памяти вызывать MapViewOfFile
повторно с указанием флага MEM_COMMIT и размера блока который система способна выделить?
делал нечто подобное с VirtualAlloc, а теперь хочу разобраться как это можно сделать для образа файла.
Здравствуйте, Alexander G, Вы писали:
AG>Здравствуйте, Poseidon, Вы писали:
P>>Здравствуйте! Не секрет что mapviewoffile терпит неудачу при работе с достаточно большим по размеру файлом. P>>Вопрос — можно ли это вылечить если сначала вызвать CreateFileMapping или MapViewOfFile с флагом MEM_RESERVE?
AG>Нет. AG>1. MapViewOfFile не может мапить в указанную память. MapViewOfFileEx может, но та память должна быть свободна, а не зарезервирована. AG>2. Неудача приманивания больших файлов может быть из-за отсутствия соответствующего непрерывного куска адресного пространства. Но к нехватке физической памяти это мало относится.
AG>Что может помочь: использование x64 и сборка с /LARGEADDRESSAWARE. Тогда будет 8 TB адресного пространства, 128 TB начиная с Windows 8.1
использую
lpvBase=MapViewOfFile(hFileMap,FILE_MAP_WRITE,0,0,cb);
if (NULL==lpvBase) dwError=GetLastError();
if (NULL==lpvBase) {
n=FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, dwError, 0, (LPTSTR) &lpMsgBuf, 0, NULL); ...
пишет "недостаточно памяти для обработки команды"
хотя файл не такой уж большой, чуть менее 1 ГБ
на диске 19 ГБ свободно
можно ли заранее узнать какой объем можно безопасно маппить?
Здравствуйте, Poseidon, Вы писали:
P>Здравствуйте! Не секрет что mapviewoffile терпит неудачу при работе с достаточно большим по размеру файлом. P>Вопрос — можно ли это вылечить если сначала вызвать CreateFileMapping или MapViewOfFile с флагом MEM_RESERVE? P>Для достаточно большой области памяти. P>А потом узнать объем памяти которую можно закомитить (кстати какой функцией это можно сделать?) P>Заключить код работы с памятью в SEH и при возникновении ошибки доступа к памяти вызывать MapViewOfFile P>повторно с указанием флага MEM_COMMIT и размера блока который система способна выделить?
P>делал нечто подобное с VirtualAlloc, а теперь хочу разобраться как это можно сделать для образа файла.
непонятно вот что в работе маппинга
CreateFileMapping ... nSizeMax) — выделяет мне область памяти с МАКСИМАЛЬНЫМ размером который мне нужен
MapViewOfFile(Ex) — можно по частям, предварительно вызвав UnmapViewOfFile
А что происходит с выделенной областью памяти?? Она мне непрерывная нужна! Где гарантия что MapView по частям спроецирует
адрес именно в нужное место?
Может лучше VirtualAlloc + ReadFile использовать?
Иными словами мне нужна большая единая область памяти в которую можно маппить или считывать файлы (целиком или частями), проводить запись-чтение этой памяти и затем сбросить эту область на диск в виде одного большого файла.
Может быть выделить область для маппинга размером допустим 100 мб,
большую непрерывную область выделить функцией VirtualAlloc и использовать AWE для обмена данными между маппингом и основной памятью?
А потом сбросить всю память на диск функцией WriteFile?
Здравствуйте, Poseidon, Вы писали:
P>Здравствуйте, Poseidon, Вы писали:
P>>Здравствуйте! Не секрет что mapviewoffile терпит неудачу при работе с достаточно большим по размеру файлом. P>>Вопрос — можно ли это вылечить если сначала вызвать CreateFileMapping или MapViewOfFile с флагом MEM_RESERVE? P>>Для достаточно большой области памяти. P>>А потом узнать объем памяти которую можно закомитить (кстати какой функцией это можно сделать?) P>>Заключить код работы с памятью в SEH и при возникновении ошибки доступа к памяти вызывать MapViewOfFile P>>повторно с указанием флага MEM_COMMIT и размера блока который система способна выделить?
P>>делал нечто подобное с VirtualAlloc, а теперь хочу разобраться как это можно сделать для образа файла.
P>непонятно вот что в работе маппинга P>CreateFileMapping ... nSizeMax) — выделяет мне область памяти с МАКСИМАЛЬНЫМ размером который мне нужен P>MapViewOfFile(Ex) — можно по частям, предварительно вызвав UnmapViewOfFile
P>А что происходит с выделенной областью памяти?? Она мне непрерывная нужна! Где гарантия что MapView по частям спроецирует P>адрес именно в нужное место?
Зачем такая гарантия нужна? Пусть проецирует, куда получается.
При указании смещения в параметре MapViewOfFile будет спроецирована именно та часть маппинга, которая соответствует этому смещению.
Таким образом, куски MapViewOfFile "рваные", но их базовый CreateFileMapping остаётся непрерывным.
P>Может быть выделить область для маппинга размером допустим 100 мб, P>большую непрерывную область выделить функцией VirtualAlloc и использовать AWE для обмена данными между маппингом и основной памятью?
Маппинги AWE всё равно проецируются куда попало, как и MapViewOfFile, и точно так же достаточно большой AWE не будет проецироваться одним куском.
AWE вообще не для этого, а чтобы получить доступ к большому объёму физической памяти.
С учётом того, что x86 версии Windows всё равно ограничены 4 ГБ физической памяти,
а на х64 можно получить её куда более простым способом, собрав 64-битное приложение, AWE сейчас вообще ни для чего не нужно.
Здравствуйте, Alexander G, Вы писали:
AG>AWE вообще не для этого, а чтобы получить доступ к большому объёму физической памяти. AG>С учётом того, что x86 версии Windows всё равно ограничены 4 ГБ физической памяти, AG>а на х64 можно получить её куда более простым способом, собрав 64-битное приложение, AWE сейчас вообще ни для чего не нужно.
получается в 32 битном приложении нереально выделить область памяти более 1 гб без особых ухищрений? даже опция линкера не особо помогла, вместо 940 мегабайт система выделяет всего 1150
Здравствуйте, Poseidon, Вы писали:
P>получается в 32 битном приложении нереально выделить область памяти более 1 гб без особых ухищрений?
Основная причина перехода на x64 — именно возможность адресовать много памяти без ухищрений, так то целые числа больше 4 млрд не особо нужны большинству приложений.
P>даже опция линкера не особо помогла, вместо 940 мегабайт система выделяет всего 1150
Количество выделяемой памяти ещё зависит от её занятости и фрагментации.
Можно попробовать в самом начале работы приложения выделить, там цифры могут получиться побольше.
(Ну а могут не получиться, статически загруженные до main DLL-ки тоже занимают память, причём, благодаря ASLR, этот процесс варьируется между запусками)
Здравствуйте, Poseidon, Вы писали:
P>А что происходит с выделенной областью памяти?? Она мне непрерывная нужна!
Это те же проблемы, что и с простой аллокацией непрерывного куска памяти. Не важно, для файл-мэппинга мы хотим память или для внутреннего массива данных, эти запросы будет обслуживать один и тот же менеджер памяти. И с запросами "подай гигабайт, подай гигабайт" на 32 битах будет так же тухло как у Паниковского в "Золотом Телёнке".
или переходим на 64 бита
или отказываемся от требования непрерывности (благо мэпать файл можно разными частями одновременно, с заданным смещением/размером каждая)