Как увеличить максимальное количество дочерних процессов, которые могут быть вызваны службой Windows - ограничения рабочей области рабочего стола
В: У меня есть служба Windows, которая порождает множество дочерних процессов. Кажется, что существует некоторый предел, около 100, где процесс не может быть запущен. Вызов CreateProcess() возвращается с pid, но тогда процесс просто не реализуется. Если вместо этого я запустил наш сервер в качестве консольного приложения, этот лимит исчезнет. Кроме того, если я установил флаг DETACHED_PROCESS, этот предел более чем удваивается. Однако я получаю сбои, если я устанавливаю DETACHED_PROCESS и вызываю CreateProcesssWithLogonW().
Ответы
Ответ 1
Это проблема "куча рабочего стола". Очень хорошее обсуждение можно найти здесь:
Обзор кучи рабочего стола
Обратите внимание, что это относится только к программам, которые работают как сервисы, потому что размер кучи рабочего стола по умолчанию для служб намного меньше, чем для приложений.
В нашем случае мы смогли запустить около 100 дочерних процессов до исчерпания ресурсов без изменений. С изменением это число может быть значительно увеличено.
Это ответ, который мы предоставили нашим конечным пользователям на нашей базе знаний:
ПРЕДУПРЕЖДЕНИЕ: это влияет на кучу рабочего стола всех служб! Не делайте это больше, чем необходимо, или вы будете вынуждать систему потреблять больше ресурсов, и вы можете столкнуться с проблемами в общем размере кучи рабочего стола.
Если вы обнаружите, что не можете открыть более 100 проектов, даже на очень большом сервере RAM, возможно, вы столкнулись с ограничением размера "кучи рабочего стола Windows".
Проблема заключается в том, что сеансы служб под окнами (где запущены службы) имеют меньше этого "рабочего пространства" для создания окон.
Короткий вариант:
-
Службы получают небольшие кучи рабочего стола, чем интерактивные сеансы.
-
Размер рабочей кучи рабочего стола ограничивает количество окон
-
Каждый подсервер создает одно или несколько "окон", даже если мы не видим их.
Решение:
-
Резервное копирование реестра перед внесением любых изменений!
-
Запустите regedit.exe как администратор
-
Изменить значение реестра:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SubSystems\Windows
-
Вы увидите строку типа:
%SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,20480,768 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=winsrv:ConServerDllInitialization,2 ServerDll=sxssrv,4 ProfileControl=Off MaxRequestThreads=16
Критический бит:
SharedSection=1024,20480,768
Второе число (20480) - это размер для интерактивных сеансов. Третье число (768) - это размер неинтерактивных (сервисных) сеансов. Обратите внимание, как третье число на 26 раз меньше второго. Экспериментально мы обнаружили, что это изменение:
SharedSection=1024,20480,2048
Увеличен предел проекта от 106 до 270, почти идеально масштабируется с размером кучи. Выберите значение, которое отражает максимальное количество проектов, которые вы ожидаете открыть одновременно всеми пользователями в системе. Не делайте это значение больше необходимого, и не больше 8192, так как каждая служба в вашей системе будет потреблять больше драгоценного ресурса.
Вам нужно будет перезагрузить, чтобы эти новые настройки вступили в силу.
Ответ 2
У нас было много серверов удаленного рабочего стола, которые нам нужно было протестировать, поэтому мы написали powershell script для запроса AD для наших RD-серверов, а затем применили это изменение реестра. Наслаждайтесь
$newValue = "%SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,20480,2048 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=sxssrv,4 ProfileControl=Off MaxRequestThreads=16"
$origValue = "%SystemRoot%\system32\csrss.exe ObjectDirectory=\Windows SharedSection=1024,20480,768 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=sxssrv,4 ProfileControl=Off MaxRequestThreads=16"
if ($update) {
Clear-Variable update
}
$updateConfirm= [System.Windows.Forms.MessageBox]::Show("Update Desktop Heap Limitation to 2048?" , "Status" , 4)
if ($updateConfirm -eq "YES" ) {
$update = $true
} else {
$revertConfirm= [System.Windows.Forms.MessageBox]::Show("Revert Desktop Heap Limitation to 768?" , "Status" , 4)
if ($revertConfirm -eq "YES" ) {
$update = $false
}
}
if (($updateConfirm -ne "YES") -and ($revertConfirm -ne "YES")) {
Write-Host "User did not specify whether to update or revert Desktop Heap Limitation. Exiting Setup."
Read-Host "Press Enter to exit."
break
}
#Import Active Directory PowerShell module
if (Test-Path C:\Users\${env:USERNAME}\Documents\WindowsPowerShell\Modules\ActiveDirectory\ActiveDirectory.psm1) {
Import-Module ActiveDirectory -prefix AD
} else {
$s = New-PSSession -computerName DC01WDC01
Invoke-command { import-module ActiveDirectory } -session $s
Export-PSSession -session $s -commandname *-AD* -outputmodule ActiveDirectory -allowclobber
Import-Module ActiveDirectory -prefix AD
Remove-PSSession -session $s
}
$servers = Get-ADADComputer -Filter {(Name -Like "RDS*")} | Select -Expand Name
foreach ($server in $servers) {
Write-Host "Working on $server" -ForegroundColor Magenta
if(!(Test-Connection -ComputerName $server -Count 1 -quiet)) {
Write-Warning "$server : Offline"
Continue
}
if ($update -eq $true) {
Invoke-Command -ComputerName $server -ArgumentList $newValue -ScriptBlock {
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems" -Name "Windows" -Value $args[0]
$result = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems" | SELECT Windows
if ($result.Windows -like "*SharedSection=1024,20480,2048*") {
Write-Host "Successfully reverted Desktop Heap Limit to 2048" -ForegroundColor Green
} else {
Write-Warning "Update to registry value unsuccessful on $env:ComputerName"
}
}
} elseif ($update -eq $false) {
Invoke-Command -ComputerName $server -ArgumentList $origValue -ScriptBlock {
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems" -Name "Windows" -Value $args[0]
$result = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems" | SELECT Windows
if ($result.Windows -like "*SharedSection=1024,20480,768*") {
Write-Host "Successfully reverted Desktop Heap Limit to 768" -ForegroundColor Green
} else {
Write-Warning "Update to registry value unsuccessful on $env:ComputerName"
}
}
}
}