Выделение и освобождение памяти
Сведения о функциях API приведены в таблице ниже.
Использование API
Страницы виртуальной памяти могут быть свободными, зарезервированными или зафиксированными. Свободные страницы, которые были использованы для выделения региона виртуальной памяти, становятся зарезервированными. Зарезервированные страницы могут как отображаться, так и не отображаться на физическую память. Зарезервированные страницы, которые отображаются на физическую память, являются зафиксированными.
Фиксация страниц региона виртуальной памяти, который выделен вызовом функции KnVmAllocate(), может выполняться тремя способами:
- В полном объеме при выделении региона.
- В полном объеме или частично после выделения региона (вызовом функции
KnVmCommit()). - По мере обращения к виртуальным адресам (в "ленивом" режиме).
При использовании первого способа весь требуемый объем физической памяти выделяется сразу после резервирования региона виртуальной памяти. При использовании второго и третьего способов регион виртуальной памяти резервируется без выделения физической памяти. Это позволяет экономить физическую память, если зарезервированный регион виртуальной памяти фактически не потребуется или будет использован частично. Также выделение региона виртуальной памяти без фиксации быстрее, чем с фиксацией.
В "ленивом" режиме физическая память выделяется при фактическом обращении к региону виртуальной памяти. При этом фиксируется страница, содержащая адрес обращения, и несколько страниц до или после нее.
Если вызвать функцию KnVmAllocate() с флагами VMM_FLAG_COMMIT и VMM_FLAG_LOCKED, то будет зарезервирован и зафиксирован регион виртуальной памяти. Если вызвать функцию KnVmAllocate() с флагом VMM_FLAG_LOCKED, но без флага VMM_FLAG_COMMIT, то будет зарезервирован регион виртуальной памяти, для фиксации которого нужно использовать функцию KnVmCommit(). Если вызвать функцию KnVmAllocate() с флагом VMM_FLAG_COMMIT, но без флага VMM_FLAG_LOCKED, то будет зарезервирован регион виртуальной памяти с фиксацией в "ленивом" режиме. Если вызвать функцию KnVmAllocate() без флагов VMM_FLAG_COMMIT и VMM_FLAG_LOCKED, то будет зарезервирован регион виртуальной памяти, фиксация которого будет выполняться в "ленивом" режиме, но только после применения функции KnVmCommit(). Фиксацию виртуальной памяти в "ленивом" режиме, которая по умолчанию разрешена в системе, можно запретить на уровне системы, если задать параметр запуска ядра vmm.overcommit=disabled, или в отдельном процессе, если указать флаг KOS_TASK_FLAG_LOCK_MEM при создании процесса с помощью API task.h. В этом случае функции KnVmAllocate() и KnVmCommit() либо фиксируют виртуальную память с выделением всего требуемого объема физической памяти, либо завершаются с ошибкой при недостатке физической памяти, даже если параметр flags функции KnVmAllocate() требует фиксации в "ленивом" режиме.
По умолчанию система настроена так, что поток исполнения, обращающийся к виртуальной памяти, которая должна быть зафиксирована в "ленивом" режиме, блокируется в случае нехватки физической памяти, ожидая ее освобождения. Если задать параметр запуска ядра vmm.overcommit=exception, то вместо блокирования потока исполнения возникает исключение типа EXCEPTION_OVERCOMMIT. (Константа EXCEPTION_OVERCOMMIT определена в заголовочном файле sysroot-*-kos/include/hal/exc_codes.h из состава KasperskyOS SDK.) В отдельном процессе можно переопределить установку, применяемую на уровне системы. Для этого нужно указать флаг KOS_TASK_FLAG_OVERCOMMIT_EXCEPTION или KOS_TASK_FLAG_OVERCOMMIT_WAIT_FREE при создании процесса с помощью API task.h.
При отображении буфера MDL, буфера DMA или региона памяти MMIO на память процесса выделяется регион виртуальной памяти. Этот регион выделяет функция, выполняющая отображение.
В начале и/или конце региона виртуальной памяти может располагаться охранная страница. Эта страница никогда не фиксируется, и при обращении к ней возникает исключение, которое сигнализирует о выходе за границы региона.
Чтобы изменить права доступа к региону виртуальной памяти, нужно вызвать функцию KnVmProtect(). Можно полностью закрыть, а затем снова открыть доступ к региону с сохранением содержимого.
Чтобы освободить физическую память, сохранив резервирование виртуальных адресов, нужно вызвать функцию KnVmDecommit() или KnVmReset(). При этом содержимое региона виртуальной памяти будет потеряно. После освобождения физической памяти вызовом функции KnVmDecommit() для последующего использования региона виртуальной памяти нужно вызвать функцию KnVmCommit(). После освобождения физической памяти вызовом функции KnVmReset() регион виртуальной памяти можно использовать без дополнительных действий. Этот регион виртуальной памяти будет соответствовать выделенному вызовом функции KnVmAllocate() с флагом VMM_FLAG_COMMIT, но без флага VMM_FLAG_LOCKED.
Функции KnVmProtect(), KnVmDecommit() и KnVmReset() нельзя использовать, если на регион виртуальной памяти отображен буфер MDL, буфер DMA или регион памяти MMIO.
Чтобы освободить регион виртуальной памяти, нужно вызвать функцию KnVmUnmap(). В результате вызова этой функции зарезервированные страницы становятся свободными независимо от того, зафиксированы они или нет, а также освобождается физическая память, отображенная на зафиксированные страницы.
Функция KnVmUnmap() освобождает виртуальные адреса региона, на который отображен буфер MDL, но не удаляет буфер MDL. Также эту функцию нельзя использовать, если на регион виртуальной памяти отображен буфер DMA или регион памяти MMIO.
Функции KnVmCommit(), KnVmProtect(), KnVmDecommit(), KnVmReset() и KnVmUnmap() можно применять как для всего выделенного региона виртуальной памяти, так и для его части.
Приведенные в этом разделе функции являются базой для реализации функций выделения и освобождения памяти библиотеки libkos, а также таких интерфейсов POSIX, как malloc(), calloc(), realloc(), free(), mmap(), munmap().
Сведения о функциях API
Функции vmm_api.h
Функция | Сведения о функции |
|---|---|
| Назначение Выделяет (резервирует и опционально фиксирует) регион виртуальной памяти. Параметры
Возвращаемые значения В случае успеха возвращает базовый адрес выделенного региона виртуальной памяти, иначе возвращает Дополнительные сведения В параметре
Допустимые комбинации флагов, задающих права доступа к региону виртуальной памяти:
|
| Назначение Фиксирует регион виртуальной памяти. Параметры
Возвращаемые значения В случае успеха возвращает |
| Назначение Отменяет фиксацию региона виртуальной памяти. Параметры
Возвращаемые значения В случае успеха возвращает |
| Назначение Изменяет права доступа к региону виртуальной памяти. Параметры
Возвращаемые значения В случае успеха возвращает Дополнительные сведения В параметре
|
| Назначение Освобождает регион виртуальной памяти. Параметры
Возвращаемые значения В случае успеха возвращает |
| Назначение Отменяет фиксацию региона виртуальной памяти. Параметры
Возвращаемые значения В случае успеха возвращает |