MapViewOfFile зависает на устройстве Windows Mobile 6

У меня есть проект Visual Studio 2008 C++ для Windows Mobile 6 ARMV4I, где я использую файлы с отображением памяти. К сожалению, это приводит к блокировке устройства. Я могу продемонстрировать проблему с этим кодом:

#include <list>
#include <algorithm>

int _tmain(int argc, _TCHAR* argv[])
{
    DWORD alloc_size = 256;
    DWORD alloc_max = 16 * 1024 * 1024;
    DWORD alloc_count = alloc_max / alloc_size;

    HANDLE f = ::CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, alloc_max, NULL );

    std::list< void* > l;
    for( DWORD i = 0; i < alloc_count; ++i )
    {
        // device freezes after 65529 iterations
        l.push_back( ::MapViewOfFile( f, FILE_MAP_READ | FILE_MAP_WRITE, 0, i * alloc_size, alloc_size ) );
    }

    std::for_each( l.rbegin(), l.rend(), ::UnmapViewOfFile );
    ::CloseHandle( f );
    return 0;
}

Эмулятор Windows Mobile 6 Classic зависает после 65529 итераций в моем тестировании. Это что-то, что я делаю неправильно, или есть проблема с платформой, о которой я должен знать?

Спасибо, PaulH

Изменить: увеличение до /STACK:1048576,4096 позволяет выполнить 65535 итераций, прежде чем устройство зависнет.

Edit2: Согласно GlobalMemoryStatus непосредственно перед сбоем, на устройстве имеется 70,5 МБ / 94,1 МБ свободной физической памяти.

Edit3: я могу создать два MMF и загрузить их оба размером до 65500 * 256 байт. Но ни один из них не может по отдельности превышать 65535 выделений. На самом деле, размер alloc не имеет значения. Я могу сократить его пополам до 128 байт каждый, но все равно терплю >65535 итераций.

Edit4: Поддержка MMF реальным файлом, похоже, не имеет значения. Сбой в > 65535 итерациях.


person PaulH    schedule 12.05.2011    source источник


Ответы (3)


В Windows память управляется страницами. Кроме того, существует минимальная степень детализации при размещении этих страниц. В настольной Windows размер страницы обычно составляет 4 КБ, а минимальная степень детализации обычно составляет 64 КБ. Если вы попытаетесь использовать VirtualAlloc или MapViewOfFile с меньшим размером, он будет округлен, и вы потеряете немного оперативной памяти.

Я почти уверен, что размер страницы будет 4 КБ и на Windows Mobile, поэтому для каждого 256-байтового MapViewOfFile на самом деле должно быть зарезервировано минимум 4 КБ. Вы можете позвонить по номеру GetSystemInfo, чтобы получить эти номера для себя.

Это означает, что ваш код на самом деле резервирует минимум 256 МиБ и, возможно, намного больше, если степень детализации распределения выше. Ваше приложение исчерпывает свое адресное пространство.

person Cory Nelson    schedule 12.05.2011
comment
Почему вы не получаете исключение нехватки памяти? - person Ben Schwehn; 12.05.2011
comment
@Cory Nelson - MapViewOfFile для Windows Mobile не требует от вас использования гранулярности выделения 4 КБ для › 32-битных адресов. msdn.microsoft.com/en-us/library/aa914405.aspx - person PaulH; 12.05.2011
comment
Хороший вопрос. Раньше я разрабатывал для Windows Mobile, но у меня никогда не заканчивалась память. Я не уверен, какое поведение проявлять в этой ситуации. - person Cory Nelson; 12.05.2011
comment
@Paul: Конечно, это так. 32-битное младшее слово смещения должно быть выровнено по нему, и если оно выровнено, то комбинированное 64-битное смещение будет таким же. - person Cory Nelson; 12.05.2011
comment
@Paul: И хотя MapViewOfFile позволяет вам указать размер представления меньше, чем степень детализации, он фактически округлит его за кулисами. - person Cory Nelson; 12.05.2011
comment
@Corey - Из MSDN: Выравнивание 64 КБ не требуется для dwFileOffsetLow. - person PaulH; 12.05.2011
comment
@Corey - разве функция CreateFileMapping не выполняет фактическое вырезание ОЗУ? Я понимаю, что это должно быть выровнено по страницам, но MapViewOfFile - это просто смещения в этом сопоставлении файлов. Это неправильно? - person PaulH; 12.05.2011
comment
@Paul: Я на самом деле не уверен, что сейчас означает выравнивание 64 КБ. Это и раздел для dwFileOffsetLow противоречат друг другу. - person Cory Nelson; 12.05.2011
comment
@Paul: CreateFileMapping на самом деле не резервирует никакого адресного пространства, все это делается в MapViewOfFile. Насколько я знаю, он не объединяет несколько перекрывающихся представлений одной страницы в одно представление за кулисами. - person Cory Nelson; 12.05.2011
comment
@Corey - Если я укажу фактический дескриптор файла, CreateFileMapping резервирует место в файле. Я предположил, что это работает так же для анонимного MMF, поскольку MSDN ничего не говорит против этого. Есть ли способ узнать, когда память зарезервирована и сколько? - person PaulH; 12.05.2011
comment
Резервирование пространства в резервном файле и резервирование виртуального адресного пространства — это не одно и то же. Я имею в виду как в VirtualAlloc с MEM_RESERVE. Даже когда вы используете файл для его поддержки, он все равно должен сопоставить его с вашим виртуальным адресным пространством, чтобы дать вам указатель. - person Cory Nelson; 12.05.2011
comment
@Cory - я проверил, и у меня тоже не заканчивается виртуальная память. Оба эти codeproject.com/KB/windows/VirtualMemory.aspx и GlobalMemoryStatus показывают У меня осталось ~ 28 МБ виртуальной машины для моего процесса. - person PaulH; 12.05.2011

Согласно этому (см. рис. 4), адресное пространство составляет всего 256 МБ. выделены для использования с отображаемыми в память файлами. 64 КБ * 4 КБ = 256 МБ, поэтому вы достигли предела.

person Luke    schedule 12.05.2011
comment
Это для CE6. На приведенном выше графике показан CE5, у которого есть 1 ГБ, доступный для MMF. Windows Mobile 6.5 основана на CE5. en.wikipedia.org/wiki/Windows_Mobile - person PaulH; 12.05.2011
comment
Ах, ты прав. Возможно, существует просто жесткое ограничение на просмотр сопоставления файлов в 64 КБ (должно быть достаточно для всех). Однако я не вижу полезности того, что делает ваш код. Почему бы просто не сопоставить все это и сохранить несколько указателей в представлении? - person Luke; 13.05.2011
comment
Это то, что я делаю. MapViewOfFile просто дает мне указатель на MMF. Память отображается CreateFileMapping. - person PaulH; 13.05.2011
comment
Я имею в виду, просто вызовите MapViewOfFile один раз для всего этого, а затем вручную управляйте своими собственными указателями в этом представлении. - person Luke; 13.05.2011

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

-ПолХ

person PaulH    schedule 13.05.2011