Объясните линейку из двух дополнений математики подсчета свободной виртуальной памяти - PullRequest
5 голосов
/ 01 ноября 2010

У меня есть приложение Visual Studio 2008 C ++ для Windows Mobile 6.x, в котором я подсчитываю объем свободной виртуальной памяти, доступной для данного процесса.(Я понимаю, что это не учитывает фрагментацию.) Мой код выглядит в основном так:

MEMORY_BASIC_INFORMATION mbi = { 0 };

/// total free memory available to the process
DWORD free = 0;

/// base memory address for the given process index (2-33). 
DWORD slot_base_addr = process_index * 0x02000000;

/// look at each memory region for the process. 
for( DWORD offset = 0x10000; 
     offset < 0x02000000; 
     offset += mbi.RegionSize )
{
    ::VirtualQuery( ( void* )( slot_base_addr + offset ), 
                    &mbi, 
                    sizeof( MEMORY_BASIC_INFORMATION ) );

    if( mbi.State == MEM_FREE )
    {
        free += ( mbi.RegionSize - ( ( ~( DWORD )mbi.BaseAddress + 1 ) & 0xffff ) ) & 0xffff0000;
    }
}
NKDbgPrintfW( L"%d bytes free\r\n", free );

Я могу подтвердить с другими API, что это, кажется, работает отлично.Мой вопрос заключается в том, что делает эта строка:

free += ( mbi.RegionSize - ( ( ~( DWORD )mbi.BaseAddress + 1 ) & 0xffff ) ) & 0xffff0000;

Почему это не просто:

free += mbi.RegionSize;

Я нашел предыдущую строку в сообщении Usenet от MSFTсотрудник Росс Джордан.

Спасибо, PaulH


Редактировать:

Например.Для слота процесса 2 это список каждого блока свободной памяти с объемом свободной памяти, заданным как алгоритмом Росса Джордана (RS), так и только RegionSize (RS).

Slot: 2. Range: 0x04000000 - 0x06000000
    RS:    16,384 bytes RJ:         0 bytes diff: 16384
    RS:     4,096 bytes RJ:         0 bytes diff: 4096
    RS:     4,096 bytes RJ:         0 bytes diff: 4096
    RS:     4,096 bytes RJ:         0 bytes diff: 4096
    RS:     4,096 bytes RJ:         0 bytes diff: 4096
    RS:     4,096 bytes RJ:         0 bytes diff: 4096
    RS:    36,864 bytes RJ:         0 bytes diff: 36864
    RS:    65,536 bytes RJ:    65,536 bytes diff: 0
    RS:    53,248 bytes RJ:         0 bytes diff: 53248
    RS:     4,096 bytes RJ:         0 bytes diff: 4096
    RS:     4,096 bytes RJ:         0 bytes diff: 4096
    RS:     4,096 bytes RJ:         0 bytes diff: 4096
    RS:     4,096 bytes RJ:         0 bytes diff: 4096
    RS:     4,096 bytes RJ:         0 bytes diff: 4096
    RS: 7,671,808 bytes RJ: 7,667,712 bytes diff: 4096
    RS: 1,921,024 bytes RJ: 1,900,544 bytes diff: 20480
    RS: 7,491,584 bytes RJ: 7,471,104 bytes diff: 20480
    RS: 3,252,224 bytes RJ: 3,211,264 bytes diff: 40960
    RS:   262,144 bytes RJ:   262,144 bytes diff: 0

RS: Total VM Free: 20,811,776 bytes.
RJ: Total VM Free: 20,578,304 bytes.

Правка 2:

Ганс привел меня к ответу.Это просто причудливый способ сделать это, но при условии, что размер выделения составляет 64 КБ.

SYSTEM_INFO si = { 0 };
::GetSystemInfo( &si );

free += mbi.RegionSize - mbi.RegionSize % si.dwAllocationGranularity;

1 Ответ

2 голосов
/ 01 ноября 2010

Степень детализации распределения для VirtualAlloc обычно составляет 64 КБ.Он пытается сделать что-то осмысленное, если база AllocationBase не кратна 64 КБ.Я не думаю, что это вообще имеет смысл, его битовые маски все еще предполагают гранулярность 64 КБ, и он не использует SYSTEM_INFO.dwAllocationGranularity.Который имеет этот комментарий:

В прошлом это значение было жестко закодировано как 64 КБ, но для других аппаратных архитектур могут потребоваться другие значения.это не 64 КБ, этот код будет генерировать ненужные значения.Просто убери его, иди по RegionSize.

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