Использование стека ядра

Размер стека в режиме ядра ограничен примерно тремя страницами. Поэтому при передаче данных во внутренние подпрограммы драйверы не могут передавать большие объемы данных в стек ядра.

Чтобы избежать переполнения пространства стека в режиме ядра, используйте следующие рекомендации по проектированию:

  • Избегайте глубоко вложенных вызовов из одной внутренней подпрограммы драйвера в другую, если каждая подпрограмма передает данные в стек ядра.

  • Убедитесь, что вы ограничиваете количество рекурсивных вызовов, которые могут происходить, если вы разрабатываете драйвер с рекурсивной подпрограммой.

Другими словами, структура дерева вызовов драйвера должна быть относительно плоской. Можно вызвать подпрограммы IoGetStackLimits и IoGetRemainingStackSize , чтобы определить доступное пространство стека ядра, или KeExpandKernelStackAndCallout для его расширения. Обратите внимание, что размер стека в режиме ядра может отличаться для разных аппаратных платформ и разных версий операционной системы.

Из-за отсутствия пространства стека ядра возникает неустранимая системная ошибка. Поэтому драйверу лучше выделить системное пространство, чем иссякать пространство стека ядра. Однако непагрегированные пулы также являются ограниченным системным ресурсом.

Как правило, стек в режиме ядра находится в памяти, однако иногда его можно вывести на страницу, если поток переходит в состояние ожидания, указывающее пользовательский режим. Сведения о том, как временно отключить разбиение стека ядра для текущего потока, см. в разделе KeSetKernelStackSwapEnable . По соображениям производительности не рекомендуется глобально отключать разбиение по страницам стека ядра, но если вы хотите сделать это во время сеанса отладки, см. раздел Отключение разбиения по страницам стеков ядра.

Так как стек ядра может быть выгружаем, будьте осторожны при передаче буферов на основе стека (т. е. локальных переменных) в DMA или любую подпрограмму, которая выполняется в DISPATCH_LEVEL или выше.