Выделение памяти System-Space

Важно!

DIS ExAllocatePool, рассматриваемые в этом разделе, устарели в Windows 10 версии 2004 и заменены ExAllocatePool2 и ExAllocatePool3. Дополнительные сведения см. в разделе Обновление устаревших вызовов ExAllocatePool для ExAllocatePool2 и ExAllocatePool3.

Драйверы могут использовать пространство, выделенное системой в расширениях устройств , в качестве глобальных областей хранения для получения сведений о конкретном устройстве. Драйверы могут использовать только стек ядра для передачи небольших объемов данных во внутренние подпрограммы. Некоторые драйверы должны выделять дополнительные, большие объемы системной памяти, как правило, для буферов ввода-вывода.

Чтобы выделить пространство в буфере ввода-вывода, лучшими подпрограммами выделения памяти являются MmAllocateNonCachedMemory, MmAllocateContiguousMemorySpecifyCache, AllocateCommonBuffer (если устройство драйвера использует шину master DMA или режим автоматической инициализации контроллера DMA системы) или ExAllocatePoolWithTag.

Непагрегированные пулы обычно фрагментируются по мере выполнения системы, поэтому подпрограмма DriverEntry драйвера должна вызывать эти подпрограммы, чтобы настроить любые долгосрочные буферы ввода-вывода, необходимые драйверу. Каждая из этих подпрограмм, за исключением ExAllocatePoolWithTag, выделяет память, выровненную по границе процессора (определяемой размером строки кэша данных процессора), чтобы обеспечить оптимальную производительность.

Драйверы должны выделять буферы ввода-вывода как можно экономично, так как непагрегированная память пула является ограниченным системным ресурсом. Как правило, драйверу следует избегать многократного вызова этих подпрограмм поддержки для запроса выделения менее PAGE_SIZE так как каждое выделение, которое меньше PAGE_SIZE также поставляется с заголовком пула, который используется для внутреннего управления выделением.

Советы по экономичному выделению буферного пространства драйвера

Чтобы экономически выделить память буфера ввода-вывода, имейте в виду следующее:

  • Каждый вызов MmAllocateNonCachedMemory или MmAllocateContiguousMemorySpecifyCache всегда возвращает полный кратный размер страницы системы, независимо от размера запрошенного выделения. Таким образом, запросы меньше страницы округляются до полной страницы, а все оставшиеся байты на странице тратятся впустую; Они недоступны драйверу, который вызвал функцию, и непригодны для другого кода в режиме ядра.

  • Каждый вызов AllocateCommonBuffer использует по крайней мере один регистр карты объектов адаптера, который сопоставляет по крайней мере один байт и не более одной страницы. Дополнительные сведения о регистрах карт и использовании общих буферов см. в разделе Объекты адаптера и DMA.

Выделение памяти с помощью ExAllocatePoolWithTag

Драйверы также могут вызывать ExAllocatePoolWithTag, указывая одно из следующих системных POOL_TYPE значений для параметра PoolType :

  • Тип пула = NonPagedPool для любых объектов или ресурсов, не хранящихся в расширении устройства или расширении контроллера, к которым драйвер может получить доступ, пока он работает на APC_LEVEL IRQL>.

    Для этого значения PoolTypeExAllocatePoolWithTag выделяет объем памяти, запрашиваемый, если указанное значение NumberOfBytes меньше или равно PAGE_SIZE. В противном случае все оставшиеся байты на последней выделенной странице будут потрачены впустую: недоступны вызывающей стороне и непригодны для другого кода в режиме ядра.

    Например, в x86 запрос на выделение 5 килобайт (КБ) возвращает две страницы размером 4 КБ. Последние 3 КБ второй страницы недоступны вызывающей или другой вызывающей. Чтобы избежать использования непагированного пула, драйвер должен эффективно выделять несколько страниц. В этом случае, например, драйвер может сделать два выделения, одно для PAGE_SIZE, а другое для 1 КБ, чтобы выделить в общей сложности 5 КБ.

    Примечание Начиная с Windows Vista система автоматически добавляет дополнительную память, поэтому два выделения не нужны.

  • Тип пула = PagedPool для памяти, которая всегда доступна в irQL <= APC_LEVEL и не находится в пути записи файловой системы.

ExAllocatePoolWithTag возвращает указатель NULL , если не удается выделить запрошенное количество байтов. Драйверы всегда должны проверка возвращаемого указателя. Если его значение равно NULL, подпрограмма DriverEntry (или любая другая подпрограмма драйвера, возвращающая значения NTSTATUS) должна возвращать STATUS_INSUFFICIENT_RESOURCES или обрабатывать условие ошибки, если это возможно.