Стеки потоков Windows

Ранее мы обсуждали память процессов и она является общей памятью для потоков. Но у каждого потока есть свой блок памяти в которой находятся стеки потоков.










Теория




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




Диспетчер памяти выделяет каждому потоку 2 стека: стек ядра и пользовательский стек. Про режимы работы я писал здесь.




По умолчанию на пользовательский стек вначале выделяется 1 МБ, но подтверждается только первая страница. Стек может расти по мере необходимости, при этом стек не может сжиматься. Программисты должны правильно рассчитать возможное количество потоков в одном процессе, чтобы не сильно нагружать виртуальную память. Например если приложение запустит 1000 потоков, то будет выделено 1 ГБ виртуальной памяти только для стеков пользовательского режима.




Но еще важнее стек ядра, который нагружает физическую память. Для него выделяется 12 КБ для x86 и 16 КБ для x64. Такие стеки находятся в системном адресном пространстве ядра. В отличии от пользовательских стеков, стеки ядра могут и расширяться и сжиматься.




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




Практика




Чтобы попытаться создать максимальное количество потоков в системе можно воспользоваться утилитой testlimit. Опция -t создаёт потоки, а опция -n 64 — указывает что для каждого потока нужно резервировать 64 KB.




Но прежде запустите «Диспетчер задач» и перейдите на вкладку «Подробности«. Потому что остановить утилиту вы сможете только из диспетчера задач, если успеете (или если успеете нажать Ctrl+C). Потому что у вас скорее всего не хватит оперативной памяти для такого количества потоков.




Если приготовились запускайте:




> Testlimit64.exe -t -n 64




Вот как это выглядит в диспетчере задач:




Диспетчер задач. при выполнении Testlimit64.exe -t -n 64




На моей машине получилось дойти до 309600 потоков в одном процессе при 16 GB памяти. Это 309600 * 4KB = 1 209 MB в пользовательском режиме. И 309600 * 16KB = 4837 МБ в режиме ядра. И в общем получается = 6046 MB.




Чтобы увидеть увеличение стека ядра можно воспользоваться утилитой RamMap. Почему-то в 64 разрядной версии системы не запустился RAMMap64a.exe, зато работает RAMMap.exe.




Вот например стек ядра (Kernel Stack) до и после запуска Testlimit64.exe -t -n 64:




Устройство Windows. Стеки, изображение №1




До запуска  Testlimit64.exe -t -n 64
До запуска Testlimit64.exe -t -n 64




После запуска  Testlimit64.exe -t -n 64
После запуска Testlimit64.exe -t -n 64




А на вкладке «Processes» в утилите «RAMMap» мы видим наш процесс «Testlimit64.exe«:




RamMap. Вкладка "Processes"








Вернуться к оглавлению



2021-09-07T17:14:35
Администрирование Windows