Отображенный в память файл std :: allocator при замораживании устройства WM6 - PullRequest
9 голосов
/ 05 мая 2011

У меня есть проект Visual Studio 2008 C ++ для Windows Mobile 6.x, где мне нужно больше памяти, чем доступно в слоте для процесса 32 МБ.Итак, я смотрю на использование файлов с отображенной памятью.Я создал стандартную реализацию распределителя, которая заменяет new / delete на CreateFileMapping и MapViewOfFile .

. Предполагаемое использование - что-то вроде этого:

struct Foo
{
    char a[ 1024 ];
};

int _tmain( int argc, _TCHAR* argv[] )
{
    std::vector< boost::shared_ptr< Foo > > v;
    for( int i = 0; i < 40000; ++i )
    {
        v.push_back( boost::allocate_shared< Foo >( MappedFileAllocator< Foo >() ) );
    }
    return 0;
}

С std::allocator я могу получить 28197 итераций в этом примере, прежде чем получу исключение std::bad_allocMappedFileAllocator я получаю 32371 итераций, прежде чем устройство полностью зависнет и должно быть перезагружено.Поскольку мое устройство имеет 512 МБ ОЗУ, я ожидал, что смогу получить гораздо больше итераций из этого цикла.

Моя MappedFileAllocator реализация:

template< class T >
class MappedFileAllocator
{
public:
    typedef T         value_type;
    typedef size_t    size_type;
    typedef ptrdiff_t difference_type;
    typedef T*        pointer;
    typedef const T*  const_pointer;
    typedef T&        reference;
    typedef const T&  const_reference;

    pointer address( reference r ) const { return &r; };
    const_pointer address( const_reference r ) const { return &r; };

    /// convert a MappedFileAllocator<T> to a MappedFileAllocator<U>
    template< class U >
    struct rebind { typedef MappedFileAllocator< U > other; };

    MappedFileAllocator() throw() : mapped_file_( INVALID_HANDLE_VALUE ) { };

    template< class U >
    explicit MappedFileAllocator( const MappedFileAllocator< U >& other ) throw()
        : mapped_file_( INVALID_HANDLE_VALUE )
    {
        if( other.mapped_file_ != this->mapped_file_ )
        {
            ::DuplicateHandle( GetCurrentProcess(), 
                other.mapped_file_,
                GetCurrentProcess(),
                &this->mapped_file_,
                0,
                FALSE,
                DUPLICATE_SAME_ACCESS );
        }
    };

    pointer allocate( size_type n, const void* /*hint*/ = 0 )
    {
        if( n > max_size() )
           throw std::bad_alloc();

        if( n > 0 )
        {
            size_type buf_size = n * sizeof( value_type );
            mapped_file_ = ::CreateFileMapping( INVALID_HANDLE_VALUE, 
                NULL,
                PAGE_READWRITE,
                0,
                buf_size,
                L"{45E4FA7B-7B1E-4939-8CBB-811276B5D4DE}" );

            if( NULL == mapped_file_ )
                throw std::bad_alloc();

            LPVOID f = ::MapViewOfFile( mapped_file_, 
                FILE_MAP_READ | FILE_MAP_WRITE, 
                0, 
                0, 
                buf_size );

            if( NULL == f )
            {
                ::CloseHandle( mapped_file_ );
                mapped_file_ = INVALID_HANDLE_VALUE;
                throw std::bad_alloc();
            }
            return reinterpret_cast< T* >( f );
        }

        return 0;
    };

    void deallocate( pointer p, size_type n )
    {
        if( NULL != p )
        {
            ::FlushViewOfFile( p, n * sizeof( T ) );
            ::UnmapViewOfFile( p );
        }
        if( INVALID_HANDLE_VALUE != mapped_file_ )
        {
            ::CloseHandle( mapped_file_ );
            mapped_file_ = INVALID_HANDLE_VALUE;
        }
    };

    size_type max_size() const throw() 
    { 
        return std::numeric_limits< size_type >::max() / sizeof( T );
    };

    /// handle to the memory-mapped file
    HANDLE mapped_file_;

private:

    /// disallow assignment
    void operator=( const MappedFileAllocator& );

}; // class MappedFileAllocator

Кто-нибудь может подсказать, где я могу ошибаться с моей реализацией MappedFileAllocator?

Спасибо, PaulH

Ответы [ 3 ]

1 голос
/ 26 июля 2011

Проверьте, поддерживает ли boost :: interprocess Windows Mobile.У них есть средства для создания отображенных в память файлов и использования памяти для выделения любого фрагмента данных, который вы хотите:

http://www.boost.org/doc/libs/1_47_0/doc/html/interprocess/sharedmemorybetweenprocesses.html#interprocess.sharedmemorybetweenprocesses.mapped_file

0 голосов
/ 09 апреля 2014

Я только что получил значок «популярный вопрос» для этого, поэтому я решил (запоздало) опубликовать ответ.У меня кончились доступные ручки.В ядре Windows Mobile есть неподписанный короткий счетчик, связанный с переполнением выделения дескриптора.Как только это произойдет, устройство зависнет.

0 голосов
/ 05 мая 2011

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

Это подтверждается количеством итераций, которые вы получаете. Похоже, вы можете отобразить до 60% общей памяти на вашем устройстве.

Вероятно, вы можете заставить это работать с большими разделами, если откроете реальный файл (используя OpenFile) и отобразите это вместо использования INVALID_FILE_HANDLE в CreateFileMapping. Но будьте осторожны с вашим флеш-хранилищем (и производительностью!), Если вы собираетесь много писать в файловое отображение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...