VirtualAlloc и MapViewOfFile
От: Poseidon СССР  
Дата: 15.02.18 16:53
Оценка:
Здравствуйте! Не секрет что mapviewoffile терпит неудачу при работе с достаточно большим по размеру файлом.
Вопрос — можно ли это вылечить если сначала вызвать CreateFileMapping или MapViewOfFile с флагом MEM_RESERVE?
Для достаточно большой области памяти.
А потом узнать объем памяти которую можно закомитить (кстати какой функцией это можно сделать?)
Заключить код работы с памятью в SEH и при возникновении ошибки доступа к памяти вызывать MapViewOfFile
повторно с указанием флага MEM_COMMIT и размера блока который система способна выделить?

делал нечто подобное с VirtualAlloc, а теперь хочу разобраться как это можно сделать для образа файла.
Re: VirtualAlloc и MapViewOfFile
От: enigmas Ниоткуда  
Дата: 15.02.18 18:05
Оценка: +1
Здравствуйте, Poseidon, Вы писали:

P>Здравствуйте! Не секрет что mapviewoffile терпит неудачу при работе с достаточно большим по размеру файлом.

P>Вопрос — можно ли это вылечить если сначала вызвать CreateFileMapping или MapViewOfFile с флагом MEM_RESERVE?
P>Для достаточно большой области памяти.
P>А потом узнать объем памяти которую можно закомитить (кстати какой функцией это можно сделать?)
P>Заключить код работы с памятью в SEH и при возникновении ошибки доступа к памяти вызывать MapViewOfFile
P>повторно с указанием флага MEM_COMMIT и размера блока который система способна выделить?

P>делал нечто подобное с VirtualAlloc, а теперь хочу разобраться как это можно сделать для образа файла.


MEM_RESERVE обычно используется если память надо выделить по определенному адресу. Если адрес не имеет значение, можно просто MEM_COMMIT.

Если какие то есть проблемы с большими файлами (о чем я не знаю), можно просто маппить не весь файл, а его часть?
См. 3 последние аргумента MapViewOfFile.
The Enigma Protector — software protection system
http://enigmaprotector.com/
Re: VirtualAlloc и MapViewOfFile
От: Alexander G Украина  
Дата: 15.02.18 19:08
Оценка: +4
Здравствуйте, Poseidon, Вы писали:

P>Здравствуйте! Не секрет что mapviewoffile терпит неудачу при работе с достаточно большим по размеру файлом.

P>Вопрос — можно ли это вылечить если сначала вызвать CreateFileMapping или MapViewOfFile с флагом MEM_RESERVE?

Нет.
1. MapViewOfFile не может мапить в указанную память. MapViewOfFileEx может, но та память должна быть свободна, а не зарезервирована.
2. Неудача приманивания больших файлов может быть из-за отсутствия соответствующего непрерывного куска адресного пространства. Но к нехватке физической памяти это мало относится.

Что может помочь: использование x64 и сборка с /LARGEADDRESSAWARE. Тогда будет 8 TB адресного пространства, 128 TB начиная с Windows 8.1
Русский военный корабль идёт ко дну!
Re[2]: VirtualAlloc и MapViewOfFile
От: Poseidon СССР  
Дата: 15.02.18 22:14
Оценка:
Здравствуйте, 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 ГБ свободно

можно ли заранее узнать какой объем можно безопасно маппить?
Re[3]: VirtualAlloc и MapViewOfFile
От: Alexander G Украина  
Дата: 16.02.18 05:36
Оценка: 3 (1) +1
Здравствуйте, Poseidon, Вы писали:

P>хотя файл не такой уж большой, чуть менее 1 ГБ

P>на диске 19 ГБ свободно

P>можно ли заранее узнать какой объем можно безопасно маппить?


Можно, например, составить карту памяти через VirtualQuery, или попробовать VirtualAlloc и потом освободить.
Но ненадёжно: память может стать фрагментированной между проверкой и вызовом.

Я так понимаю, система 64-битное, приложение 32-битное?

1 ГБ это тот объём, для которого неудача примапить в обычное 32 битное приложение предсказуема — там всего 2 ГБ адресного пространства.

Простое включение /LARGEADDRESSAWARE увеличивает его до 4 ГБ:


Это увеличивает шансы на успех.

Перевод на x64 вместе со включенным /LARGEADDRESSAWARE даёт от 8 ТБ, ну то есть примапить 1 ГБ вообще не проблемой становится.

(Перевод на х64 без включения /LARGEADDRESSAWARE не даёт ничего)
Русский военный корабль идёт ко дну!
Re[3]: VirtualAlloc и MapViewOfFile
От: Pavel Dvorkin Россия  
Дата: 16.02.18 15:30
Оценка:
Здравствуйте, Poseidon, Вы писали:

Скачай вот это

https://docs.microsoft.com/en-us/sysinternals/downloads/vmmap

P>использую


Вот сюда что-то вроде getch(), чтобы программа остановилась. Запусти ее без отладки.

P>lpvBase=MapViewOfFile(hFileMap,FILE_MAP_WRITE,0,0,cb);


И когда она до этого места дойдет, запусти vmmap и посмотри, какой там самый большой непрерывный свободный участок.

Если < размера файла — действительно не хватает
Если > — ищи у себя ошибку.
With best regards
Pavel Dvorkin
Re: VirtualAlloc и MapViewOfFile
От: Poseidon СССР  
Дата: 16.02.18 18:50
Оценка:
Здравствуйте, 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?
Отредактировано 16.02.2018 19:54 Poseidon . Предыдущая версия . Еще …
Отредактировано 16.02.2018 19:45 Poseidon . Предыдущая версия .
Отредактировано 16.02.2018 19:01 Poseidon . Предыдущая версия .
Re[2]: VirtualAlloc и MapViewOfFile
От: Alexander G Украина  
Дата: 17.02.18 05:41
Оценка:
Здравствуйте, 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 сейчас вообще ни для чего не нужно.
Русский военный корабль идёт ко дну!
Отредактировано 17.02.2018 6:07 Alexander G . Предыдущая версия .
Re[3]: VirtualAlloc и MapViewOfFile
От: Poseidon СССР  
Дата: 17.02.18 11:46
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>AWE вообще не для этого, а чтобы получить доступ к большому объёму физической памяти.

AG>С учётом того, что x86 версии Windows всё равно ограничены 4 ГБ физической памяти,
AG>а на х64 можно получить её куда более простым способом, собрав 64-битное приложение, AWE сейчас вообще ни для чего не нужно.

получается в 32 битном приложении нереально выделить область памяти более 1 гб без особых ухищрений? даже опция линкера не особо помогла, вместо 940 мегабайт система выделяет всего 1150
Отредактировано 17.02.2018 13:30 Poseidon . Предыдущая версия .
Re[4]: VirtualAlloc и MapViewOfFile
От: Alexander G Украина  
Дата: 19.02.18 13:20
Оценка:
Здравствуйте, Poseidon, Вы писали:

P>получается в 32 битном приложении нереально выделить область памяти более 1 гб без особых ухищрений?


Основная причина перехода на x64 — именно возможность адресовать много памяти без ухищрений, так то целые числа больше 4 млрд не особо нужны большинству приложений.

P>даже опция линкера не особо помогла, вместо 940 мегабайт система выделяет всего 1150


Количество выделяемой памяти ещё зависит от её занятости и фрагментации.
Можно попробовать в самом начале работы приложения выделить, там цифры могут получиться побольше.
(Ну а могут не получиться, статически загруженные до main DLL-ки тоже занимают память, причём, благодаря ASLR, этот процесс варьируется между запусками)
Русский военный корабль идёт ко дну!
Re[2]: VirtualAlloc и MapViewOfFile
От: Mr.Delphist  
Дата: 21.02.18 12:49
Оценка:
Здравствуйте, Poseidon, Вы писали:

P>А что происходит с выделенной областью памяти?? Она мне непрерывная нужна!


Это те же проблемы, что и с простой аллокацией непрерывного куска памяти. Не важно, для файл-мэппинга мы хотим память или для внутреннего массива данных, эти запросы будет обслуживать один и тот же менеджер памяти. И с запросами "подай гигабайт, подай гигабайт" на 32 битах будет так же тухло как у Паниковского в "Золотом Телёнке".

 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.