Q : 많은 하위 프로세스를 생성하는 Windows 서비스가 있습니다. 프로세스가 시작될 수없는 약 100 정도의 한계가있는 것으로 보입니다. CreateProcess() 호출은 pid로 되돌아 오지만, 프로세스가 구현되지 않습니다. 서버를 콘솔 응용 프로그램으로 실행하면이 한계가 사라집니다. 또한 DETACHED_PROCESS 플래그를 설정하면이 제한이 두 배가됩니다. 그러나, 나는 DETACHED_PROCESS를 설정하고 CreateProcesssWithLogonW()를 호출하면 실패한다.Windows 서비스 - 데스크톱 힙 제한으로 생성 될 수있는 하위 프로세스의 최대 수를 늘리는 방법
답변
이것은 "데스크톱 힙"문제입니다. 아주 좋은 논의는 여기에서 찾을 수 있습니다 : 서비스의 기본 데스크톱 힙 크기는 응용 프로그램에 대한보다 훨씬 작기 때문에이 만는 서비스로 실행중인 프로그램에 적용
참고.
우리는 약 100 개의 하위 프로세스를 변경하지 않고 리소스가 부족해지기 전에 실행할 수있었습니다. 변경으로이 숫자는 상당히 증가 할 수 있습니다.
이것은 우리가 우리의 지식에 대한 우리의 최종 사용자에게 준 대답은 :
경고 :이 모든 서비스의 데스크톱 힙 영향을 미친다! 필요 이상으로 커지지 않거나 더 많은 리소스를 사용하도록 시스템을 밀어 넣으십시오. 사용 가능한 총 데스크톱 힙 크기 문제가 발생할 수 있습니다.
매우 큰 RAM 서버에서도 약 100 개가 넘는 프로젝트를 열 수 없다면 Windows "데스크톱 힙 크기"제한을 초과했을 수 있습니다.
문제는 서비스를 실행하는 Windows의 서비스 세션에서 창을 만들 때 사용할 수있는 "데스크톱 힙"공간이 적다는 것입니다.
짧은 버전입니다 :
서비스는 대화 형 세션보다 작은 데스크톱 힙을 얻을.
데스크톱 힙 크기는 우리가 볼 수없는 경우에도 각 부 서버는 하나 이상의 "창"을 만들고 창
의 수를 제한합니다.
해결 : 레지스트리를 변경하기 전에
백업!
실행 regedit.
%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
당신은 같은 문자열을 볼 수
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SubSystems\Windows
: 관리자
편집 레지스트리 값으로 EXE 두 번째 뉴 mber (20480)는 대화식 세션의 크기입니다. 세 번째 숫자 (768)는 비대화 형 (서비스) 세션의 크기입니다. 세 번째 숫자가 두 번째 숫자보다 26 배 작은 것을 확인하십시오. 실험적으로이 값을 다음으로 변경했습니다.
SharedSection=1024,20480,2048
프로젝트 제한이 106에서 270으로 증가하여 힙 크기가 거의 완벽하게 조정되었습니다. 시스템의 모든 사용자가 동시에 열 수있는 최대 프로젝트 수를 반영하는 값을 선택하십시오. 이 값을 필요 이상으로 크게하지 말고 시스템의 각 서비스가 소중한 자원을 더 많이 소비하므로 8192를 넘지 마십시오.
이러한 새로운 설정을 적용하려면 재부팅해야합니다.
우리는이 테스트를 위해 많은 원격 데스크톱 서버가 필요했기 때문에 RD 서버에 대해 AD를 쿼리하고이 레지스트리 변경 내용을 적용 할 수있는 powershell 스크립트를 작성했습니다. Enjoy
$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"
}
}
}
}
유감스럽게도 우리 상황에서는 설정이 제대로 작동하지 않았지만 대용량 스크립트를 사용하여 테스트 할 많은 수의 컴퓨터가있는 다른 사람에게 도움이 될 수도 있습니다. :) – Shaun
나를 위해 일했으나 변경 사항을 적용한 후 재부팅해야만 적용됩니다. – user3725395
포크 닝 서비스에 적용되는 이러한 '데스크톱 힙'쓰기에서 언어를 이해할 수는 없지만이 대답은 숨김을 저장했습니다. – covener
놀랍게도 Windows 2008 Server Web Edition (Vista Core), Windows 2008 Server R2 (Windows 7 코어) 및 Windows 2012 Server R2 (Windows 8.1 코어)에는 동일한 제한 사항이 적용되었습니다. 저는 1024204804096으로 광산을 변경했으며 자원 사용에 별다른 영향을 미치지 않으면 서 모든 서버에서 최대 스레드 수를 16에서 32로 늘렸지 만 다른 서버에서 동시에 실행되는 다른 프로세스를 생성하기 위해 해당 서버에서 실행되는 서비스의 능력이 현저히 증가했습니다. 감사! –
+1 매우 명확한 설명 및 해결 방법. 그러나 레코드에 대해서는 서비스에서이 많은 하위 프로세스를 작성하는 경우 잘못 처리하고있는 것입니다. :-) [UNIX에서 코드를 이식하는 경우 다시 설계하려고 노력할 가치가 없을 수도 있습니다.] –