오늘은 디스크 공간을 다 써버리는 문제에 대해서 살펴 보도록 하겠습니다.


윈도우, 리눅스 등의 운영체제에서 디스크 공간을 다 써버려서 특정 애플리케이션이 오동작 하거나 시스템 파티션의 공간이 부족해져서 시스템이 멈추는 현상을 본 적이 있을 것 입니다. 윈도우, 리눅스 모두 디스크 공간을 확인하는 방법이 있는데 아무래도 리눅스 쪽이 좀 더 강력합니다.


-------------------------------------------------------- Linux -----------------------------------------------------------
리눅스 에서는 마운트 되어 있는 모든 파티션의 크기, 사용 중인 공간, 사용 가능한 공간을 df 명령을 통해서 확인할 수 있습니다.


출력 결과를 보면 바로 디스크 공간이 얼마나 남아 있는지 확인할 수 있습니다. 그런데 /dev/sda2를 보면 전체 크기 20G에서 사용량 4G를 빼면 16G가 나와야 할 것 같은데 15G가 나오는 것을 확인할 수 있습니다. 리눅스가 긴급 상황을 위해서 Reserved block을 따로 만들어 놓는다고 합니다. (tune2fs 명령을 사용해서 Reserved block의 크기를 확인할 수 있습니다.)

Red hat 문서를 보면 Reserved block을 5% 할당하게 되어 있는데 파일 시스템이 큰 경우 이 크기를 줄일 수 있다고 합니다.

https://access.redhat.com/solutions/1189733


디스크 공간이 많이 사용된 것을 확인했으먼 어떤 디렉토리가 많이 사용하고 있는지 확인해야 합니다. 이 때 사용할 수 있는 명령이 du 입니다.


일반적으로 많이 발생하지는 않지만 df 명령을 실행했을때 충분한 디스크 공간이 있는데 공간이 부족하다는 오류가 발생하는 경우 입니다. 이 경우에는 inode가 고갈되었는지 확인해봐야 합니다. inode의 사용률은 df -i 명령을 통해서 확인할 수 있습니다. /dev/sda2 파티션은 1,310,720 개의 inode가 있고 그중 109,878 개가 사용되었습니다.

inode가 부족한 현상이 발생하면 해당 파티션의 파일을 지우는 작업을 통해서 inode를 확보할 수 있으며 문제 해결을 위해서는 inode가 충분히 할당되도록 파일 시스템을 새로 만들어야 합니다.

https://access.redhat.com/solutions/641333


리눅스는 부팅 시점에 자동으로 파일 시스템 체크 명령인 fsck를 실행 합니다. 파일시스템이 손상된 경우 해당 파이션을 umount 한 후 fsck 명령으로 조치를 취합니다.


-------------------------------------------------------- Windows --------------------------------------------------------

Windows 에서는 df 명령이 없고 GUI를 사용하거나 WMI를 사용해서 Win32_logicaldisk의 정보를 확인해야 합니다. WMI는 WMIC 라는 명령을 사용해서 확인할 수도 있고 PowerShell을 사용할 수도 있습니다. 안타깝게도 Windows 에서는 사용률을 %로 보여주지는 않습니다.


디스크 공간이 많이 사용되었을 때 du 명령을 사용하여 어떤 디렉토리나 파일이 공간을 차지하는지 확인할 수 있는데 Windows에 기본 명령에는 du가 없고 sysinternals에서 du 를 다운 받아야 합니다.


https://docs.microsoft.com/en-us/sysinternals/downloads/du


sysinternals의 du 는 리눅스의 du 와는 다르게 동작하고 리눅스에 있는 sort, tail 등의 명령이 Windows에는 없기 때문에 PowerShell을 사용해서 비슷하게 만들어 보았습니다. (du 에서 배너를 없애는 -q 를 사용했지만 배너가 출력되고 있습니다. )


Windows 에서 Disk 공간이 부족할 때 확인해봐야 할 것은 2가지가 있습니다. 첫째 백업을 위해 사용되는 새도 복사본 저장소의 사용률 입니다. 새도 복사본은 각 디스크에 "System Volume Information" 이라는 디렉토리 아래에 있는데 이 디렉토리는 System 만 접근할 수 있게 설정되어 있어 du가 크기를 확인할 수 없습니다. (vssadmin 명령으로 사용량을 확인해야 합니다.), 둘째 du를 사용하는 계정이 접근할 수 없는 디렉토리 (Admin도 사용자 전용으로 설정된 디렉토리에 접근할 수 없습니다.) 또는 디렉토리 또는 파일이 배타적인 접근 속성을 가지고 있는 경우 크기를 확인할 수 없습니다.


Windows 에서 사용하는 NTFS에는 inode와 같은 개념이 없고 최대 4,294,967,295 개까지 파일, 디렉토리를 만들 수 있습니다.

http://www.ntfs.com/ntfs_vs_fat.htm


Windows에서도 부트 시점에 autochk 가 실행되어 손상된 파일 시스템을 치료할 수 있습니다. 그리고 chkdsk 명령을 사용해서 볼륨를 검사 및 오류를 수정할 수 있습니다. /F 옵션을 사용해서 오류를 수정하려고 할 경우 볼륨을 분리 한 후 실행할 수 있습니다. 



볼륨의 크기가 클 경우 chkdsk를 실행하여 오류를 수정하는데 많은 시간이 걸리는데 Windows 2008 부터 Self-healing, Spot fix 라는 기능이 들어가서 오류가 발생할 경우 바로 fix를 하고 있습니다. (새로운 파일 시스템인 REFS에는 Chkdsk가 필요 없다고 합니다.)

https://blogs.technet.microsoft.com/doxley/2008/10/29/self-healing-ntfs/

https://blogs.msdn.microsoft.com/b8/2012/05/09/redesigning-chkdsk-and-the-new-ntfs-health-model/


감사합니다.




'Windows & Linux' 카테고리의 다른 글

디스크가 가득 차는 경우  (0) 2018.12.15
부팅 과정 및 복구 (Grub)  (0) 2018.06.17
성능 모니터링 (sysstat, sar)  (0) 2018.06.16
IO 부하 (iostat, iotop)  (0) 2018.06.06
시스템 부하 (top)  (0) 2018.06.03
시스템 부하 확인 (uptime)  (2) 2018.06.02

VMware 에서 실행되는 Windows VM이 시스템 행 현상이 있다고 하여 분석을 진행해 보았습니다.


먼저 !vm 명령을 싱행해서 메모리 상태를 확인해 보았는데 별다른 문제가 확인되지 않았습니다.

0: kd> !vm

Page File: \??\C:\pagefile.sys

  Current:   1048576 Kb  Free Space:    807844 Kb

  Minimum:   1048576 Kb  Maximum:     10485500 Kb

 

Physical Memory:          4194156 (   16776624 Kb)

Available Pages:          3479978 (   13919912 Kb)

ResAvail Pages:           4063051 (   16252204 Kb)

Locked IO Pages:                0 (          0 Kb)

Free System PTEs:      4294989313 (17179957252 Kb)

Modified Pages:             13432 (      53728 Kb)

Modified PF Pages:          12747 (      50988 Kb)

Modified No Write Pages:        0 (          0 Kb)

NonPagedPool    0:             33 (        132 Kb)

NonPagedPoolNx  0:          32181 (     128724 Kb)

NonPagedPool    1:              0 (          0 Kb)

NonPagedPoolNx  1:              0 (          0 Kb)

NonPagedPool Usage:           168 (        672 Kb)

NonPagedPoolNx Usage:       40172 (     160688 Kb)

NonPagedPool Max:      4294967296 (17179869184 Kb)

PagedPool  0:               79908 (     319632 Kb)

PagedPool  1:               51553 (     206212 Kb)

PagedPool  2:                   0 (          0 Kb)

PagedPool Usage:           131461 (     525844 Kb)

PagedPool Maximum:     4160749568 (16642998272 Kb)

Processor Commit:             917 (       3668 Kb)

Session Commit:             16179 (      64716 Kb)

Syspart SharedCommit 0

Shared Commit:              51347 (     205388 Kb)

Special Pool:                   0 (          0 Kb)

Kernel Stacks:               8889 (      35556 Kb)

Pages For MDLs:               342 (       1368 Kb)

Pages For AWE:                  0 (          0 Kb)

NonPagedPool Commit:        38599 (     154396 Kb)

PagedPool Commit:          131461 (     525844 Kb)

Driver Commit:               9397 (      37588 Kb)

Boot Commit:                50253 (     201012 Kb)

System PageTables:            997 (       3988 Kb)

VAD/PageTable Bitmaps:       6871 (      27484 Kb)

ProcessLockedFilePages:        12 (         48 Kb)

Pagefile Hash Pages:          206 (        824 Kb)

Sum System Commit:         315470 (    1261880 Kb)

Total Private:             473164 (    1892656 Kb)

Misc/Transient Commit:       4291 (      17164 Kb)

Committed pages:           792925 (    3171700 Kb)

Commit limit:             4456300 (   17825200 Kb)




Storage에는 Pending 된 IO가 있는지 확인을 해 보았지만 Pending 된 것이 확인되지 않았습니다.

0: kd> !storunit

STORPORT Units:

==================

Product                 SCSI ID  Object            Extension         Pnd Out Ct  State

--------------------------------------------------------------------------------------

VMware     Virtual di   0  0  0  ffffab06b03a4060  ffffab06b03a41b0    0   0  0  Working

VMware     Virtual di   0  1  0  ffffab06b0399060  ffffab06b03991b0    0   0  0  Working

 

0: kd> !storunit ffffab06b03a4060

   DO: ffffab06b03a4060   Ext: ffffab06b03a41b0   Adapter: ffffab06b03cb1a0   Working

   Vendor: VMware    Product: Virtual disk      SCSI ID: (0, 0, 0)

   Claimed Enumerated

   SlowLock: Free  RemLock: 1  PageCount: 1

   QueueTagList: ffffab06b03a42b0     Node 0 Outstanding: Head: 0000000000000000  Tail: 0000000000000000  Timeout: 0 (Ticking Down)

   Node 1 Outstanding: Head: 0000000000000000  Tail: 0000000000000000  Timeout: 0 (Ticking Down)

   DeviceQueue: ffffab06b03a4340  Depth: 64  Status: Not Frozen   PauseCount: 0  BusyCount: 0

   IO Gateway: Busy Count: 0  Pause Count: 0

   Requests: Outstanding: 0  Device: 0  ByPass: 0

 

 

[Device-Queued Requests]

 

IRP               SRB Type   SRB               XRB               Command           MDL               SGList            Timeout

-----------------------------------------------------------------------------------------------------------------------------------

 

 

[Bypass-Queued Requests]

 

IRP               SRB Type   SRB               XRB               Command           MDL               SGList            Timeout

-----------------------------------------------------------------------------------------------------------------------------------

 

 

[Outstanding Requests]

 

IRP               SRB Type   SRB               XRB               Command           MDL               SGList            Timeout

-----------------------------------------------------------------------------------------------------------------------------------

 

 

[Completed Requests]

 

IRP               SRB Type   SRB               XRB               Command           MDL               SGList            Timeout

-----------------------------------------------------------------------------------------------------------------------------------




커널에서 동기화 객체를 기다리는 것이 있는지 확인해 보았지만 없었습니다.

0: kd> !locks

**** DUMP OF ALL RESOURCE OBJECTS ****

KD: Scanning for held locks.........

89274 total locks




그렇다면 CPU가 바빠서 발생하는 이슈일지 모른다고 생각해서 CPU의 상태를 확인해보았으니 IDLE 상태 였습니다.

0: kd> !cpuinfo

CP  F/M/S Manufacturer  MHz PRCB Signature    MSR 8B Signature Features

 0  6,79,1 GenuineIntel 2295 0b00002a00000000                   311b3fff

 1  6,79,1 GenuineIntel 2295 0b00002a00000000                   311b3fff

 2  6,79,1 GenuineIntel 2295 0b00002a00000000                   311b3fff

 3  6,79,1 GenuineIntel 2295 0b00002a00000000                   311b3fff

                      Cached Update Signature 0b00002a00000000

                     Initial Update Signature 0b00002a00000000

0: kd> !running

Process PID Thread           Id Pri Base Pri Next CPU CSwitches User          Kernel State              Time Reason

======= === ================ == === ======== ======== ========= ==== =============== ======= =============== ==============

Idle      0 fffff8035d3d5940  0   0        0        0  24448367    0   23h:56:06.250 Running 1d.00:48:53.796 Executive

Idle      0 ffffdf005f631000  0   0        0        1  20088217    0   23h:48:42.703 Running          3s.984 WrCalloutStack

Idle      0 ffffdf005f6b9000  0   0        0        2  18610602    0   23h:58:19.172 Running 1d.00:48:53.796 Executive

Idle      0 ffffdf005f741000  0   0        0        3  25365439    0 1d.00:00:03.219 Running 1d.00:48:53.796 Executive

 

Count: 4 | Show Unique Stacks

 

0: kd> !mex.us -cpu

4 threads: ffffdf005f6b9000 ffffdf005f741000 fffff8035d3d5940 ffffdf005f631000

    fffff8035d223ff1 nt!PpmIdleGuestExecute+0x15

    fffff8035d109eac nt!PpmIdleExecuteTransition+0xcbc

    fffff8035d10903a nt!PoIdle+0x33a

    fffff8035d17afac nt!KiIdleLoop+0x2c

 

1 stack(s) with 4 threads displayed (4 Total threads)




lpc의 상태를 확인해보니 svchost.exe가 explorer에 lpc message를 보내고 기다리는 것이 확인 됩니다.

0: kd> !lpcwait

Server Process ffffab06`b8137800  Connection Port ffffab06`b853c540  (\Device\HarddiskVolume1\Windows\explorer.exe)

 

    Client Thread        Client Wait Time     Client Message       Server Thread   

    =================    =================    =================    =================

    ffffab06`b1b28800           1:25.406      ffffce0e`5b04dcf0                                                          (\Device\HarddiskVolume1\Windows\System32\svchost.exe)

 

    1 thread waiting




svchost.exe의 Thread를 확인해보니 logoff를 처리하던 것으로 보입니다.

0: kd> kc

  *** Stack trace for last set context - .thread/.cxr resets it

 # Call Site

00 nt!KiSwapContext

01 nt!KiSwapThread

02 nt!KiCommitThreadWait

03 nt!KeWaitForSingleObject

04 nt!AlpcpSignalAndWait

05 nt!AlpcpReceiveSynchronousReply

06 nt!AlpcpProcessSynchronousRequest

07 nt!NtAlpcSendWaitReceivePort

08 nt!KiSystemServiceCopyEnd

09 ntdll!NtAlpcSendWaitReceivePort

0a RPCRT4!LRPC_BASE_CCALL::DoSendReceive

0b RPCRT4!I_RpcSendReceive

0c combase!CMessageCall::CallI_RpcSendReceive

0d combase!ThreadSendReceive

0e combase!CSyncClientCall::SwitchAptAndDispatchCall

0f combase!CSyncClientCall::SendReceive2

10 combase!SyncClientCallRetryContext::SendReceiveWithRetry

11 combase!CSyncClientCall::SendReceiveInRetryContext

12 combase!DefaultSendReceive

13 combase!CSyncClientCall::SendReceive

14 combase!CClientChannel::SendReceive

15 combase!NdrExtpProxySendReceive

16 RPCRT4!NdrpClientCall3

17 combase!ObjectStublessClient

18 combase!ObjectStubless

19 combase!RemoteReleaseRifRefHelper

1a combase!RemoteReleaseRifRef

1b combase!CStdMarshal::DisconnectCliIPIDs

1c combase!CStdMarshal::Disconnect

1d combase!CStdIdentity::{dtor}

1e combase!CStdIdentity::CInternalUnk::Release

1f netprofmsvc!ATL::IConnectionPointImpl<CImplINetworkListManager,&IID_INotifyNetworkGlobalCostEvents,ATL::CComDynamicUnkArray>::Unadvise

20 netprofmsvc!CImplINetworkListManager::UnadviseAndRemoveSessionCookie<&IID_INotifyNetworkGlobalCostEvents>

21 netprofmsvc!CImplINetworkListManager::PurgeClients

22 netprofmsvc!EnterPurgeClientsCallback

23 combase!EnterForCallback

24 combase!SwitchForCallback

25 combase!PerformCallback

26 combase!CObjectContext::InternalContextCallback

27 combase!CObjectContext::ContextCallback

28 combase!CContextSwitcher::ContextCallback

29 netprofmsvc!NetProfileManUserLogOff

2a ntdll!TppSimplepExecuteCallback

2b ntdll!TppWorkerThread

2c KERNEL32!BaseThreadInitThunk

2d ntdll!RtlUserThreadStart




Explorer는 파일을 닫는 중이었는데 백신 프로그램의 필터 드라이버인 TmXPFlt가 IO가 더 진행되지 못하게 막고 있었습니다.

0: kd> !us -p ffffab06b8137800

1 thread [stats]: ffffab06b8121080

    fffff8035d17e576 nt!KiSwapContext+0x76

    fffff8035d0d74fd nt!KiSwapThread+0x17d

    fffff8035d0d6f9f nt!KiCommitThreadWait+0x14f

    fffff8035d0d8d77 nt!KeWaitForSingleObject+0x377

    fffff8022e82bce3 TmXPFlt+0x1bce3

    fffff8022e814884 TmXPFlt+0x4884

    fffff8022e814d65 TmXPFlt+0x4d65

    fffff8022e814f65 TmXPFlt+0x4f65

    fffff8022e4b3f8d TmPreFlt!TmpQueryFullName+0x1e85

    fffff8022e4b40d8 TmPreFlt!TmpQueryFullName+0x1fd0

    fffff8022c603d15 FLTMGR!FltpPerformPostCallbacks+0x2a5

    fffff8022c603756 FLTMGR!FltpPassThroughCompletionWorker+0x76

    fffff8022c605299 FLTMGR!FltpLegacyProcessingAfterPreCallbacksCompleted+0x239

    fffff8022c603146 FLTMGR!FltpDispatch+0xb6

    fffff8035d4e75a0 nt!IopCloseFile+0x150

    fffff8035d5142c5 nt!ObCloseHandleTableEntry+0x245

    fffff8035d43098b nt!NtClose+0xcb

    fffff8035d187503 nt!KiSystemServiceCopyEnd+0x13

    00007ffe863c5ce4 ntdll!NtClose+0x14

    00007ffe83335aa2 KERNELBASE!CloseHandle+0x62

    00007ffe82f02560 SHCORE!CGenericFileHandle::Release+0x160

    00007ffe82f02082 SHCORE!CFileStream::~CFileStream+0xd2

    00007ffe82f00d35 SHCORE!CFileStream::Release+0x35

    00007ffe84b0d273 SHELL32!IconCacheSave+0x18965b

    00007ffe84983a05 SHELL32!SHDesktopMessageLoop+0x45

    00007ff694781468 Explorer!wWinMain+0x714

    00007ff694810727 Explorer!__wmainCRTStartup+0x1c7

    00007ffe83ce8364 KERNEL32!BaseThreadInitThunk+0x14

    00007ffe8638e851 ntdll!RtlUserThreadStart+0x21


1 stack(s) with 1 threads displayed (1 Total threads)



분석 결과를 보면 사용자는 Logoff를 하려고 하였는데 백신 제품이 IO를 잡고 있어서 시스템이 멈춘 것으로 보인 증상이었습니다.


'Debugging' 카테고리의 다른 글

System Hang 분석  (0) 2018.11.24
Symbol Server 설정 (공유, HTTP)  (0) 2018.03.04
[디버거 명령]!Mex.p  (0) 2017.09.25
[디버깅 명령]!mex.help  (0) 2017.09.24

오랜만에 Windows Kernel에 대한 블로그가 올라와서 정리를 해 보았습니다.

One Windows Kernel

https://techcommunity.microsoft.com/t5/Windows-Kernel-Internals/One-Windows-Kernel/ba-p/267142


Windows는 x86, x64, ARM, ARM64를 지원하고 예전에는 Itanium, PowerPC, DEC Alpha, MIPS를 지원할 정도로 다양한 하드웨어를 지원하고 Data center, Laptop, xbox, phone, IOT device를 지원할 정도로 다양한 SKU를 가지고 있습니다.

아래 이미지는 896 코어에 1792 개의 logical processor와 2TB RAM을 지원하는 Windows DataCenter 버전의 작업 관리자 이미지 입니다. (저도 이렇게 큰 장비를 본 적은 없습니다. 대형 장비 이지만 Windows 10을 쓰는 방법과 거의 유사하게 시스템을 관리할 수 있어 금방 적응할 수 있습니다.)

TaskMgr.png


Windows refactoring 에 대해서 먼저 이야기 하고 있습니다. 다양한 SKU의 Windows을 동일한 DLL로 지원을 하지만 일부 코드를 다르게 구현할 수 있도록 API set (https://docs.microsoft.com/en-us/windows/desktop/apiindex/windows-apisets) 이라는 것을 만들었습니다. 예를 들면 kernel32.dll을 그대로 사용하면서 실제 구현은 다른 DLL에 되어 있는 것입니다. (저도 API set을 자세히 분석해 본 적은 아직 없어서 자세한 내용은 나중에 정리해 봐야 할것 같습니다.)


Kernel Components

Windows NT는 마이크로 커널 유형으로 되어 있습니다. (완전한 마이크로 커널은 아닙니다.) 코어 커널 모듈이 있고 실행부라는 영역이 커널에 존재 합니다. 커널은 스레드 디스패칭, 멀티프로세서 동기화, 하드웨어 예외 핸들링 등을 처리 하고 실행부에서는 IO, 객체 관리, 메모리 관리, 프로세스 서브 시스템 등을 담당합니다.

arch.png


윈도우 컴포넌트의 크기를 코드수로 보면 아래와 같습니다. 역시 메모리가 가장 많은 코드를 가지고 있고 커널 순으로 이어집니다. 좀 더 자세한 내용을 학고 싶으면 Windows Internals 책을 구입해서 읽어보면 됩니다. 

Kernel subsystems

Lines of code

Memory Manager

501, 000

Registry

211,000

Power

238,000

Executive

157,000

Security

135,000

Kernel

339,000

Process sub-system

116,000


Scheduler

스레드는 프로그램 코드가 실행되는 가장 기본 유닛으로 Windows 스케줄러가 스케줄 합니다. 윈도우 스케줄러는 스레드 우선순위에 따라서 높은 우선순위를 가진 스레드 부터 스케줄링 합니다. 스레드는 주어진 시간 (Quantum time) 동안 실행되고 다음 스레드가 실행됩니다. 만약 높은 우선순위를 가지고 있는 스레드가 계속 실행되고 있어서 낮은 우선 순위를 가지는 스레드가 실행될 기회를 얻지 못한다면 낮은 우선순위를 가진 스레드의 우선순위가 올라가게 됩니다. 

최초에 Windows 스케줄러는 하나의 레디큐를 가지고 있었습니다. 하지만 많은 프로세서를 지원하기 시작하면서 하나의 레디큐가 병목현상을 보이게 되었고 Windows Server 2003 에서 프로세서마다 하나의 레디큐를 가지게 디자인이 변경 되었습니다. 하나의 레디큐를 사용하면서 발생했던 글로벌 락 문제가 사라졌습니다. 가장 높은 우선순위를 가지는 스레드가 실행되는 것은 보장할 수 있지만 N 개의 core를 가지는 시스템에서 최대 N 개의 높은 우선순위를 가지는 스레드가 실행된다고 말 할 수는 없습니다. (현재 실행되는 스레드보다 높은 스레드가 다른 코어에 대기 상태로 있을 수 있습니다.) Windows가 laptop 이나 태블릿 같은 CPU 파워가 낮은 시스템에 적용되면서 UI가 느려지는 현상등이 발생하게 되었습니다. 그래서 Windows 8.1 에서 스케줄러가 프로세서당 레디큐를 가지는 것과 프로세서간 공유하는 레디큐를 가지는 하디브리드 형태로 변경 되었습니다. 다른 아키텍처의 변경이 있었기 때문에 스케줄로 변경으로 인한 성능 향상이 크게 보이지는 않았습니다.

Windows 7 에서 동적인 공정 공유 스케줄러 (Dynamic Fair Share Scheduler)가 도입되었습니다. 이 기능은 터미널 서버를 위해서 도입되었습니다. 하나의 터미널 세션이 과도한 CPU 자원을 사용해서 다른 터미널 세션에 영향을 주는 것을 방지하기 위해 도입 되었습니다. 기존의 스케줄링은 세션을 고려하지 않고 스레드 우선순위만 고려해서 스케줄링 했는데 이 기능이 도입 되어 다른 세션에 영향을 주지 않게 되었습니다. Linux의 Completely Fair Scheduler와 유사한 것 입니다. Windows 8 에서 이 개념이 스케줄러 그룹으로 일반화 되었고 각 세션마다 윈도우 스케줄러가 사용됩니다. 스케줄러 그룹은 스레드 우선순위에서도 2차 인덱스 역할을 해서 어떤 스레드가 다음에 실행될지를 결정 합니다. 터미널 세션에서 모든 스케줄러 그룹은 동일한 양의 스케줄링을 받게 됩니다. 그리고 Job 오브젝트가 향상되어 CPU rate control (https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_jobobject_cpu_rate_control_information) 기능을 지원하게되어 프로세스가 사용할 수 있는 CPU 양의 hard cap과 soft cap을 제한할수 있습니다. 이 기능은 리눅스의 cgroups 과 유사 합니다.

Windows 7 이후 부터 Windows 서버는 64개 이상의 프로세서를 지원하게 됩니다. 많은 프로세서를 지원하기 위해 프로세서 그룹 이라는 개념이 도입되었습니다. 프로세서 그룹은 최대 64개 까지의 프로세서를 하나의 그룹으로 묶어서 하나의 스케줄링 단위로 만드는 것으로 부팅하는 시점에 커널에서 어떤 프로세서가 어떤 그룹에 설정될지를 결정 합니다. (64개 이하의 코어를 가질 경우 프로세서 그룹은 적합하지 않습니다.) 단일 프로세스 (SQL Server)는 프로세서 그룹에 확장될 수 있으나 개별 스레드는 하나의스케줄링 그룹에서만 실행될 수 있습니다. (응용 프로그램이 프로세서 그룹이나 NUMA에 적합하지 않을 경우 BIOS에서 프로세서를 하나의 그룹으로 인식 시킬 수 있습니다.)

64개 이상의 코어를 가지는 시스템에서 코어 수를 늘렸을 때 SQL server와 같은 제품에서 성능 향상이 많이 일어나지 않는 것이 확인 되었습니다. 코어 수가 늘어나면 디스패처 락 문제 때문에 성능 향상에 문제가 있는 것이 확인 되었습니다. 디스패처 락은 디스패치가 되는 오브젝트를 보호하는 락으로 스레드, 타이머, I/O 완료 포트, 동기화 객체 등을 보호 합니다. Windows 7 에서 디스패처 락을 제거하고 객체 별 락을 도입하였고 290%의 성능 향상을 보였습니다. 

Windows 10 (Windows Server 2016)에서는 CPU Sets이 추가 되었습니다. CPU Set은 프로세스가 시스템을 나눠서 프로세스가 특정 프로세서 그룹을 사용할 수 있게하고 다른 프로세스나 시스템이 할당된 프로세서 그룹을 사용하지 못하게 하는 것 입니다. 프로세서가 CPU set으로 설정되면 디바이스의 코드도 실행되지 않습니다. Windows 10의 Game Mode가 이 기능을 사용한다고 합니다. (https://www.windowscentral.com/windows-10-game-mode)

그 외에도 ARM 관련 내용이 일부 있습니다. 

Scheduler 라는 것이 일반 사용자나 개발자 모두에게 잘 보여지지 않는 내용인데 블로그를 통해서 간단하게나마 소개가 되었습니다. 하지만 깊이 있는 내용은 문서를 찾기 힘들고 이해 하기가 힘들기 때문에 이정도에서 마무리 하려고 합니다.






+ Recent posts